📄 pcvt_ext.c
字号:
if(color) inb(GN_INPSTAT1C); else inb(GN_INPSTAT1M); /* ATC Mode control */ outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); outb(ATC_DATAW, *sp++); if(color) inb(GN_INPSTAT1C); else inb(GN_INPSTAT1M); /* ATC Horizontal Pixel Panning */ outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); outb(ATC_DATAW, *sp++); /* VCLK2 Numerator Register */ outb(TS_INDEX, 0xd); outb(TS_DATA, *sp++); /* VCLK2 Denominator and Post-Scalar Value Register */ outb(TS_INDEX, 0x1d); outb(TS_DATA, *sp++); outb(GN_MISCOUTW, *sp++); /* Misc output register */ } /* disable access to cirrus extension registers */ outb(TS_INDEX, 6); outb(TS_DATA, 0); /* disable access to first 7 CRTC registers */ outb(addr_6845, CRTC_VSYNCE); outb(addr_6845+1, byte); vga_screen_on(); return(1);}#if PCVT_USL_VT_COMPAT/*---------------------------------------------------------------------------* * switch screen from text mode to X-mode and vice versa *---------------------------------------------------------------------------*/voidswitch_screen(int n, int oldgrafx, int newgrafx){#if PCVT_SCREENSAVER static unsigned saved_scrnsv_tmo = 0;#endif /* PCVT_SCREENSAVER */#if !PCVT_KBD_FIFO int x;#endif /* !PCVT_KBD_FIFO */ int cols = vsp->maxcol; /* get current col val */ if(n < 0 || n >= totalscreens) return;#if !PCVT_KBD_FIFO x = spltty(); /* protect us */#endif /* !PCVT_KBD_FIFO */ if(!oldgrafx && newgrafx) { /* switch from text to graphics */#if PCVT_SCREENSAVER if((saved_scrnsv_tmo = scrnsv_timeout)) pcvt_set_scrnsv_tmo(0); /* screensaver off */#endif /* PCVT_SCREENSAVER */ async_update(UPDATE_STOP); /* status display off */ } if(!oldgrafx) { /* switch from text mode */ /* video board memory -> kernel memory */ bcopy(vsp->Crtat, vsp->Memory, vsp->screen_rows * vsp->maxcol * CHR); vsp->Crtat = vsp->Memory; /* operate in memory now */ } /* update global screen pointers/variables */ current_video_screen = n; /* current screen no */#if !PCVT_NETBSD && !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200) pcconsp = &pccons[n]; /* current tty */#elif PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200 pcconsp = pccons[n]; /* current tty */#else pcconsp = pc_tty[n]; /* current tty */#endif vsp = &vs[n]; /* current video state ptr */ if(oldgrafx && !newgrafx) { /* switch from graphics to text mode */ unsigned i; /* restore fonts */ for(i = 0; i < totalfonts; i++) if(saved_charsets[i]) vga_move_charset(i, 0, 0);#if PCVT_SCREENSAVER /* activate screen saver */ if(saved_scrnsv_tmo) pcvt_set_scrnsv_tmo(saved_scrnsv_tmo);#endif /* PCVT_SCREENSAVER */ /* re-initialize lost MDA information */ if(adaptor_type == MDA_ADAPTOR) { /* * Due to the fact that HGC registers are write-only, * the Xserver can only make guesses about the state * the HGC adaptor has been before turning on X mode. * Thus, the display must be re-enabled now, and the * cursor shape and location restored. */ outb(GN_DMCNTLM, 0x28); /* enable display, text mode */ outb(addr_6845, CRTC_CURSORH); /* select high register */ outb(addr_6845+1, ((vsp->Crtat + vsp->cur_offset) - Crtat) >> 8); outb(addr_6845, CRTC_CURSORL); /* select low register */ outb(addr_6845+1, ((vsp->Crtat + vsp->cur_offset) - Crtat)); outb(addr_6845, CRTC_CURSTART); /* select high register */ outb(addr_6845+1, vsp->cursor_start); outb(addr_6845, CRTC_CUREND); /* select low register */ outb(addr_6845+1, vsp->cursor_end); } /* make status display happy */ async_update(UPDATE_START); } if(!newgrafx) { /* to text mode */ /* kernel memory -> video board memory */ bcopy(vsp->Crtat, Crtat, vsp->screen_rows * vsp->maxcol * CHR); vsp->Crtat = Crtat; /* operate on screen now */ outb(addr_6845, CRTC_STARTADRH); outb(addr_6845+1, 0); outb(addr_6845, CRTC_STARTADRL); outb(addr_6845+1, 0); }#if !PCVT_KBD_FIFO splx(x);#endif /* !PCVT_KBD_FIFO */ select_vga_charset(vsp->vga_charset); if(vsp->maxcol != cols) vga_col(vsp, vsp->maxcol); /* select 80/132 columns */ outb(addr_6845, CRTC_CURSORH); /* select high register */ outb(addr_6845+1, vsp->cur_offset >> 8); outb(addr_6845, CRTC_CURSORL); /* select low register */ outb(addr_6845+1, vsp->cur_offset); if(vsp->cursor_on) { outb(addr_6845, CRTC_CURSTART); /* select high register */ outb(addr_6845+1, vsp->cursor_start); outb(addr_6845, CRTC_CUREND); /* select low register */ outb(addr_6845+1, vsp->cursor_end); } else { sw_cursor(0); } if(adaptor_type == VGA_ADAPTOR) { unsigned i; /* switch VGA DAC palette entries */ for(i = 0; i < NVGAPEL; i++) vgapaletteio(i, &vsp->palette[i], 1); } if(!newgrafx) { update_led(); /* update led's */ update_hp(vsp); /* update fkey labels, if present */ /* if we switch to a vt with force 24 lines mode and */ /* pure VT emulation and 25 rows charset, then we have */ /* to clear the last line on display ... */ if(vsp->force24 && (vsp->vt_pure_mode == M_PUREVT) && (vgacs[vsp->vga_charset].screen_size == SIZ_25ROWS)) { fillw(' ', vsp->Crtat + vsp->screen_rows * vsp->maxcol, vsp->maxcol); } }}/*---------------------------------------------------------------------------* * Change specified vt to VT_AUTO mode * xxx Maybe this should also reset VT_GRAFX mode; since switching and * graphics modes are not going to work without VT_PROCESS mode. *---------------------------------------------------------------------------*/static voidset_auto_mode (struct video_state *vsx){ unsigned ostatus = vsx->vt_status; vsx->smode.mode = VT_AUTO; vsx->proc = NULL; vsx->pid = 0; vsx->vt_status &= ~(VT_WAIT_REL|VT_WAIT_ACK); if (ostatus & VT_WAIT_ACK) {#if 0 assert (!(ostatus&VT_WAIT_REL)); assert (vsp == vsx && vt_switch_pending == current_video_screen + 1); vt_switch_pending = 0;#else if (vsp == vsx && vt_switch_pending == current_video_screen + 1) vt_switch_pending = 0;#endif } if (ostatus&VT_WAIT_REL) { int new_screen = vt_switch_pending - 1;#if 0 assert(vsp == vsx && vt_switch_pending); vt_switch_pending = 0; vgapage (new_screen);#else if (vsp == vsx && vt_switch_pending) { vt_switch_pending = 0; vgapage (new_screen); }#endif }}/*---------------------------------------------------------------------------* * Exported function; to be called when a vt is closed down. * * Ideally, we would like to be able to recover from an X server crash; * but in reality, if the server crashes hard while in control of the * vga board, then you're not likely to be able to use pcvt ttys * without rebooting. *---------------------------------------------------------------------------*/voidreset_usl_modes (struct video_state *vsx){ /* Clear graphics mode */ if (vsx->vt_status & VT_GRAFX) { vsx->vt_status &= ~VT_GRAFX; if (vsp == vsx) switch_screen(current_video_screen, 1, 0); } /* Take kbd out of raw mode */ if (pcvt_kbd_raw && vsp == vsx) {#if PCVT_SCANSET > 1 kbd_emulate_pc(0);#endif /* PCVT_SCANSET > 1 */ pcvt_kbd_raw = 0; } /* Clear process controlled mode */ set_auto_mode (vsx);}/*---------------------------------------------------------------------------* * switch to virtual screen n (0 ... PCVT_NSCREENS-1), VT_USL version * (the name vgapage() stands for historical reasons) *---------------------------------------------------------------------------*/intvgapage(int new_screen){ int x; if(new_screen < 0 || new_screen >= totalscreens) return EINVAL; /* fallback to VT_AUTO if controlling processes died */ if(vsp->proc && vsp->proc != pfind(vsp->pid)) set_auto_mode(vsp); if(vs[new_screen].proc && vs[new_screen].proc != pfind(vs[new_screen].pid)) set_auto_mode(&vs[new_screen]); if (!vt_switch_pending && new_screen == current_video_screen) return 0; if(vt_switch_pending && vt_switch_pending != new_screen + 1) { /* Try resignaling uncooperative X-window servers */ if (vsp->smode.mode == VT_PROCESS) { if (vsp->vt_status & VT_WAIT_REL) { if(vsp->smode.relsig) psignal(vsp->proc, vsp->smode.relsig); } else if (vsp->vt_status & VT_WAIT_ACK) { if(vsp->smode.acqsig) psignal(vsp->proc, vsp->smode.acqsig); } } return EAGAIN; } vt_switch_pending = new_screen + 1; if(vsp->smode.mode == VT_PROCESS) { /* we cannot switch immediately here */ vsp->vt_status |= VT_WAIT_REL; if(vsp->smode.relsig) psignal(vsp->proc, vsp->smode.relsig); } else { struct video_state *old_vsp = vsp; switch_screen(new_screen, vsp->vt_status & VT_GRAFX, vs[new_screen].vt_status & VT_GRAFX); x = spltty(); if(old_vsp->vt_status & VT_WAIT_ACT) { old_vsp->vt_status &= ~VT_WAIT_ACT; wakeup((caddr_t)&old_vsp->smode); } if(vsp->vt_status & VT_WAIT_ACT) { vsp->vt_status &= ~VT_WAIT_ACT; wakeup((caddr_t)&vsp->smode); } splx(x); if(vsp->smode.mode == VT_PROCESS) { /* if _new_ vt is under process control... */ vsp->vt_status |= VT_WAIT_ACK; if(vsp->smode.acqsig) psignal(vsp->proc, vsp->smode.acqsig); } else { /* we are committed */ vt_switch_pending = 0;#if PCVT_FREEBSD > 206 /* * XXX: If pcvt is acting as the systems console, * avoid panics going to the debugger while we are in * process mode. */ if(pcvt_is_console) cons_unavail = 0;#endif } } return 0;}/*---------------------------------------------------------------------------* * ioctl handling for VT_USL mode *---------------------------------------------------------------------------*/intusl_vt_ioctl(Dev_t dev, int cmd, caddr_t data, int flag, struct proc *p){ int i, j, error, opri; struct vt_mode newmode; switch(cmd) { case VT_SETMODE: newmode = *(struct vt_mode *)data; opri = spltty(); if (newmode.mode != VT_PROCESS) { struct video_state *vsx = &vs[minor(dev)]; if (vsx->smode.mode == VT_PROCESS) { if (vsx->proc != p) { splx(opri); return EPERM; } set_auto_mode(vsx); } splx(opri); return 0; } /* * NB: XFree86-3.1.1 does the following: * VT_ACTIVATE (vtnum) * VT_WAITACTIVE (vtnum) * VT_SETMODE (VT_PROCESS) * So it is possible that the screen was switched * between the WAITACTIVE and the SETMODE (here). This * can actually happen quite frequently, and it was * leading to dire consequences. Now it is detected by * requiring that minor(dev) match current_video_screen. * An alternative would be to operate on vs[minor(dev)] * instead of *vsp, but that would leave the server * confused, because it would believe that its vt was * currently activated. */ if (minor(dev) != current_video_screen) { splx(opri); return EPERM; } /* Check for server died */ if(vsp->proc && vsp->proc != pfind(vsp->pid)) set_auto_mode(vsp); /* Check for server already running */ if (vsp->smode.mode == VT_PROCESS && vsp->proc != p) { splx(opri); return EBUSY; /* already in use on this VT */ } if (!ISSIGVALID(newmode.relsig) || !ISSIGVALID(newmode.acqsig) || !ISSIGVALID(newmode.frsig)) { splx(opri); return EINVAL; } vsp->smode = newmode; vsp->proc = p; vsp->pid = p->p_pid;#if PCVT_FREEBSD > 206 /* * XXX: If pcvt is acting as the systems console, * avoid panics going to the debugger while we are in * process mode. */ if(pcvt_is_console) cons_unavail = (newmode.mode == VT_PROCESS);#endif splx(opri); return 0; case VT_GETMODE: *(struct vt_mode *)data = vsp->smode; return 0; case VT_RELDISP: if (minor(dev) != current_video_screen) return EPERM; if (vsp->smode.mode != VT_PROCESS) return EINVAL; if (vsp->proc != p) return EPERM; switch(*(int *)data) { case VT_FALSE: /* process refuses to release screen; abort */ if(vt_switch_pending && (vsp->vt_status & VT_WAIT_REL)) { vsp->vt_status &= ~VT_WAIT_REL; vt_switch_pending = 0; return 0; } break; case VT_TRUE: /* process releases its VT */ if(vt_switch_pending && (vsp->vt_status & VT_WAIT_REL)) { int new_screen = vt_switch_pending - 1; struct video_state *old_vsp = vsp; vsp->vt_status &= ~VT_WAIT_REL; switch_screen(new_screen, vsp->vt_status & VT_GRAFX, vs[new_screen].vt_status & VT_GRAFX); opri = spltty(); if(old_vsp->vt_status & VT_WAIT_ACT) { old_vsp->vt_status &= ~VT_WAIT_ACT; wakeup((caddr_t)&old_vsp->smode); } if(vsp->vt_status & VT_WAIT_ACT) { vsp->vt_status &= ~VT_WAIT_ACT; wakeup((caddr_t)&vsp->smode); } splx(opri); if(vsp->smode.mode == VT_PROCESS) { /* * if the new vt is also in process * mode, we have to wait until its * controlling process acknowledged * the swit
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -