/* */ #ifdef BACKGROUND #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "vga.h" #include "libvga.h" #include "driver.h" #include "mouse/vgamouse.h" #include "keyboard/vgakeyboard.h" #include "vgabg.h" #define RELEASE 1 #define ACQUIRE 2 /* #define QUEUE_SIZE 200*/ #if 0 #define SETSIG(sa, sig, fun) {\ sa.sa_handler = fun; \ sa.sa_flags = 0; \ sa.sa_mask = vt_block_mask; \ sigaction(sig, &sa, NULL); \ } #endif #define SETSIG_RE(sa, sig, fun) {\ sa.sa_handler = fun; \ sa.sa_flags = 0; \ sa.sa_mask = __vt_block_mask_release; \ sigaction(sig, &sa, NULL); \ } #define SETSIG_AQ(sa, sig, fun) {\ sa.sa_handler = fun; \ sa.sa_flags = 0; \ sa.sa_mask = __vt_block_mask_aquire; \ sigaction(sig, &sa, NULL); \ } /*#define DEBUG */ /* Virtual console switching */ static int release_acquire=0; static int forbidvtrelease = 0; static int forbidvtacquire = 0; static int lock_count = 0; static int release_flag = 0; static int __vt_switching_not_ok = 0; static int __vt_switching_asked = 0; static int __vt_check_last_signal = 0; /* Never the same signal twice */ static sigset_t __vt_block_mask_aquire; static sigset_t __vt_block_mask_release; static sigset_t __vt_block_mask_switching; #if 0 static sigset_t vt_block_mask; unsigned char *__svga_graph_mem_orginal; unsigned char *__svga_graph_mem_check; static int __svgalib_oktowrite = 1; /* __svgalib_oktowrite tells if it is safe to write registers. */ static int __svgalib_virtual_mem_fd = -1; static int __svga_processnumber = -1; #endif static int __vt_switching_state=RELEASE; static int __vt_switching_signal_no; /* static int __vt_switching_to_queue[QUEUE_SIZE] = {0}; static int __vt_switching_signal_no_queue[QUEUE_SIZE] = {0}; static int __vt_signalqueuepointer = 0; static int __vt_signalqueuenewpointer = 0; */ /* User defined functions for vc switching. */ void (*__svgalib_go_to_background) (void) = 0; void (*__svgalib_come_from_background) (void) = 0; #endif #ifdef BACKGROUND static void releasevt_signal(int n); static void acquirevt_signal(int n); static void __releasevt_signal(int n) { /* struct sigaction siga; */ if (lock_count) { release_flag = 1; return; } #ifdef DEBUG printf("Release request.\n"); #endif forbidvtacquire = 1; /*SETSIG(siga, SVGALIB_RELEASE_SIG, releasevt_signal); */ if (forbidvtrelease) { forbidvtacquire = 0; ioctl(__svgalib_tty_fd, VT_RELDISP, 0); return; } if (__svgalib_go_to_background) (__svgalib_go_to_background) (); __vt_check_last_signal = RELEASE; __vt_switching_state=RELEASE; __svgalib_flipaway(); ioctl(__svgalib_tty_fd, VT_RELDISP, 1); #ifdef DEBUG printf("Finished release.\n"); #endif forbidvtacquire = 0; if((__svgalib_textprog&3)==3){ pid_t child; if((child=fork())==0){ execv(__svgalib_TextProg,__svgalib_TextProg_argv); } else { waitpid(child,NULL,0); }; }; /* Suspend program until switched to again. */ #ifdef DEBUG printf("Suspended.\n"); #endif __svgalib_oktowrite = 0; if (!__svgalib_runinbackground) __svgalib_waitvtactive(); #ifdef DEBUG printf("Waked.\n"); #endif } static void releasevt_signal(int n) { struct sigaction siga; #ifdef DEBUG printf("vt: rel "); #endif if (__vt_switching_not_ok || __vt_switching_asked) { if (__vt_check_last_signal != RELEASE) { __vt_switching_asked=1; __vt_switching_signal_no=n; __vt_switching_state=RELEASE; } } else { /* __svgalib_dont_switch_vt_yet(); */ if (__vt_check_last_signal != RELEASE) __releasevt_signal(n); /* sets __vt_check_last_signal */ /* __svgalib_is_vt_switching_needed(); */ } SETSIG_AQ(siga, SVGALIB_ACQUIRE_SIG, acquirevt_signal); SETSIG_RE(siga, SVGALIB_RELEASE_SIG, releasevt_signal); #ifdef DEBUG printf("ok\n"); #endif return; } static void __acquirevt_signal(int n) { /* struct sigaction siga; */ #ifdef DEBUG printf("Acquisition request.\n"); #endif /* vt_check_last_signal=ACQUIRE; */ forbidvtrelease = 1; /*SETSIG(siga, SVGALIB_ACQUIRE_SIG, acquirevt_signal); */ if (forbidvtacquire) { forbidvtrelease = 0; return; } __vt_check_last_signal = ACQUIRE; __vt_switching_state=ACQUIRE; __svgalib_flipback(); ioctl(__svgalib_tty_fd, VT_RELDISP, VT_ACKACQ); #ifdef DEBUG printf("Finished acquisition.\n"); #endif /*forbidvtrelease = 0; */ __svgalib_oktowrite = 1; if (__svgalib_come_from_background) (__svgalib_come_from_background) (); forbidvtrelease = 0; } static void acquirevt_signal(int n) { struct sigaction siga; #ifdef DEBUG printf("vt: acq "); #endif if (__vt_switching_not_ok || __vt_switching_asked) { if (__vt_check_last_signal != ACQUIRE) { __vt_switching_asked=1; __vt_switching_signal_no=n; __vt_switching_state=ACQUIRE; } } else { /* __svgalib_dont_switch_vt_yet(); */ if (__vt_check_last_signal != ACQUIRE) __acquirevt_signal(n); /* sets __vt_check_last_signal */ /* __svgalib_is_vt_switching_needed(); */ } SETSIG_RE(siga, SVGALIB_RELEASE_SIG, releasevt_signal); SETSIG_AQ(siga, SVGALIB_ACQUIRE_SIG, acquirevt_signal); #ifdef DEBUG printf("ok\n"); #endif return; } void __svgalib_dont_switch_vt_yet(void) { __vt_switching_not_ok++; return; } void __svgalib_is_vt_switching_needed(void) { __vt_switching_not_ok--; if (__vt_switching_not_ok < 0) { __vt_switching_not_ok = 0; printf("svgalib: lock warning, over done.\n"); } if (__vt_switching_not_ok) return; if (__vt_switching_asked) { /* Block signals... hmm ignore them */ sigprocmask(SIG_BLOCK,&__vt_block_mask_switching,NULL); if (__vt_switching_state==RELEASE && __vt_check_last_signal!=RELEASE) { #ifdef DEBUG printf("RELEASE "); #endif __releasevt_signal(__vt_switching_signal_no); __vt_switching_signal_no=0; __vt_switching_state=ACQUIRE; #ifdef DEBUG printf("OK.\n"); #endif } else { if (__vt_switching_state==ACQUIRE && __vt_check_last_signal!=ACQUIRE) { #ifdef DEBUG printf("ACQUIRE "); #endif __acquirevt_signal(__vt_switching_signal_no); __vt_switching_signal_no=0; __vt_switching_state=RELEASE; #ifdef DEBUG printf("OK.\n"); #endif } } __vt_switching_asked=0; sigprocmask(SIG_UNBLOCK,&__vt_block_mask_switching,NULL); } return; } /* These both variables should be static. However, oldvtmode is restored in vga.c.. so.. */ struct vt_mode __svgalib_oldvtmode; static struct vt_mode newvtmode; void __svgalib_takevtcontrol(void) { struct sigaction siga; ioctl(__svgalib_tty_fd, VT_GETMODE, &__svgalib_oldvtmode); newvtmode = __svgalib_oldvtmode; newvtmode.mode = VT_PROCESS; /* handle VT changes */ newvtmode.relsig = SVGALIB_RELEASE_SIG; /* I didn't find SIGUSR1/2 anywhere */ newvtmode.acqsig = SVGALIB_ACQUIRE_SIG; /* in the kernel sources, so I guess */ /* they are free */ sigemptyset(&__vt_block_mask_switching); sigaddset(&__vt_block_mask_switching,SVGALIB_RELEASE_SIG|SVGALIB_ACQUIRE_SIG); sigemptyset(&__vt_block_mask_aquire); sigaddset(&__vt_block_mask_aquire, SVGALIB_RELEASE_SIG); sigemptyset(&__vt_block_mask_release); sigaddset(&__vt_block_mask_release, SVGALIB_ACQUIRE_SIG); SETSIG_RE(siga, SVGALIB_RELEASE_SIG, releasevt_signal); SETSIG_AQ(siga, SVGALIB_ACQUIRE_SIG, acquirevt_signal); ioctl(__svgalib_tty_fd, VT_SETMODE, &newvtmode); return; } void vga_lockvc(void) { lock_count++; if (__svgalib_flip_status()) __svgalib_waitvtactive(); return; } void vga_unlockvc(void) { if (--lock_count <= 0) { lock_count = 0; if (release_flag) { release_flag = 0; releasevt_signal(SVGALIB_RELEASE_SIG); } } return; } void vga_runinbackground(int stat,...) { va_list params; va_start(params, stat); switch (stat) { case VGA_GOTOBACK: __svgalib_go_to_background = va_arg(params, void *); break; case VGA_COMEFROMBACK: __svgalib_come_from_background = va_arg(params, void *); break; default: __svgalib_runinbackground = stat; break; } va_end(params); } #endif