📄 qv.c
字号:
om_switch = m_switch; qp->mswitches = m_switch; } /* if we have proc waiting, and event has happened, wake him up */ if(qvrsel && (qp->ihead != qp->itail)) { selwakeup(qvrsel,0); qvrsel = 0; } /* * Okay we can take another hit now */ qv_ipl_lo = 1;}/* * Start transmission */qvstart(tp) register struct tty *tp;{ register int unit, c; register struct tty *tp0; int s; unit = minor(tp->t_dev);#ifdef CONS_HACK tp0 = &qv_tty[(unit&0xfc)+QVPCONS];#endif unit = QVCHAN(unit); s = spl5(); /* * If it's currently active, or delaying, no need to do anything. */ if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) goto out; /* * Display chars until the queue is empty, if the second subchannel * is open direct them there. Drop characters from subchannels other * than 0 on the floor. */ while( tp->t_outq.c_cc ) { c = getc(&tp->t_outq); if (unit == QVKEYBOARD)#ifdef CONS_HACK if( tp0->t_state & TS_ISOPEN ){ (*linesw[tp0->t_line].l_rint)(c, tp0); } else#endif qvputchar( c & 0xff ); } /* * Position the cursor to the next character location. */ qv_pos_cur( qv_scn->col*8, qv_scn->row*15 ); /* * If there are sleepers, and output has drained below low * water mark, wake up the sleepers. */ if ( tp->t_outq.c_cc<= tp->t_lowat ) { if (tp->t_state&TS_ASLEEP){ tp->t_state &= ~TS_ASLEEP; wakeup((caddr_t)&tp->t_outq); } } tp->t_state &= ~TS_BUSY;out: splx(s);}/* * Stop output on a line, e.g. for ^S/^Q or output flush. *//*ARGSUSED*/qvstop(tp, flag) register struct tty *tp;{ register int s; /* * Block input/output interrupts while messing with state. */ s = spl5(); if (tp->t_state & TS_BUSY) { if ((tp->t_state&TS_TTSTOP)==0) { tp->t_state |= TS_FLUSH; } else tp->t_state &= ~TS_BUSY; } splx(s);}qvputc(c)char c;{ qvputchar(c); if (c == '\n') qvputchar('\r');}/* * Routine to display a character on the screen. The model used is a * glass tty. It is assummed that the user will only use this emulation * during system boot and that the screen will be eventually controlled * by a window manager. * */qvputchar( c )register char c;{ register char *b_row, *f_row; register int i; register short *scanline; register int ote = 128; register struct qv_info *qp = qv_scn; /* * This routine may be called in physical mode by the dump code * so we check and punt if that's the case. */ if( (mfpr(MAPEN) & 1) == 0 ) return; c &= 0x7f; switch ( c ) { case '\t': /* tab */ for( i = 8 - (qp->col & 0x7) ; i > 0 ; i-- ) qvputchar( ' ' ); break; case '\r': /* return */ qp->col = 0; break; case '\010': /* backspace */ if( --qp->col < 0 ) qp->col = 0; break; case '\n': /* linefeed */ if( qp->row+1 >= qp->max_row ) qvscroll(); else qp->row++; /* * Position the cursor to the next character location. */ qv_pos_cur( qp->col*8, qp->row*15 ); break; case '\007': /* bell */ /* * We don't do anything to the keyboard until after * autoconfigure. */ if( qp->qvaddr ) qv_key_out( LK_RING_BELL ); return; default: if( c >= ' ' && c <= '~' ) { scanline = qp->scanmap; b_row = qp->bitmap+(scanline[qp->row*15]&0x3ff)*128+qp->col; i = c - ' '; if( i < 0 || i > 95 ) i = 0; else i *= 15; f_row = (char *)((int)q_font + i); /* for( i=0 ; i<15 ; i++ , b_row += 128, f_row++ ) *b_row = *f_row;*/ /* inline expansion for speed */ *b_row = *f_row++; b_row += ote; *b_row = *f_row++; b_row += ote; *b_row = *f_row++; b_row += ote; *b_row = *f_row++; b_row += ote; *b_row = *f_row++; b_row += ote; *b_row = *f_row++; b_row += ote; *b_row = *f_row++; b_row += ote; *b_row = *f_row++; b_row += ote; *b_row = *f_row++; b_row += ote; *b_row = *f_row++; b_row += ote; *b_row = *f_row++; b_row += ote; *b_row = *f_row++; b_row += ote; *b_row = *f_row++; b_row += ote; *b_row = *f_row++; b_row += ote; *b_row = *f_row++; b_row += ote; if( ++qp->col >= qp->max_col ) { qp->col = 0 ; if( qp->row+1 >= qp->max_row ) qvscroll(); else qp->row++; } } break; }}/* * Position the cursor to a particular spot. */qv_pos_cur( x, y)register int x,y;{ register struct qvdevice *qvaddr; register struct qv_info *qp = qv_scn; register index; if( qvaddr = qp->qvaddr ) { if( y < 0 || y > qp->max_cur_y ) y = qp->max_cur_y; if( x < 0 || x > qp->max_cur_x ) x = qp->max_cur_x; qp->cursor.x = x; /* keep track of real cursor*/ qp->cursor.y = y; /* position, indep. of mouse*/ qvaddr->qv_crtaddr = 10; /* select cursor start reg */ qvaddr->qv_crtdata = y & 0xf; qvaddr->qv_crtaddr = 11; /* select cursor end reg */ qvaddr->qv_crtdata = y & 0xf; qvaddr->qv_crtaddr = 14; /* select cursor y pos. */ qvaddr->qv_crtdata = y >> 4; qvaddr->qv_xcur = x; /* pos x axis */ /* * If the mouse is being used then we change the mode of * cursor display based on the pixels under the cursor */ if( mouseon ) { index = y*128 + x/8; if( qp->bitmap[ index ] && qp->bitmap[ index+128 ] ) qvaddr->qv_csr &= ~QV_CUR_MODE; else qvaddr->qv_csr |= QV_CUR_MODE; } }}/* * Scroll the bitmap by moving the scanline map words. This could * be done by moving the bitmap but it's much too slow for a full screen. * The only drawback is that the scanline map must be reset when the user * wants to do graphics. */qvscroll(){ short tmpscanlines[15]; register char *b_row; register short *scanline; register struct qv_info *qp = qv_scn; /* * If the mouse is on we don't scroll so that the bit map * remains sane. */ if( mouseon ) { qp->row = 0; return; } /* * Save the first 15 scanlines so that we can put them at * the bottom when done. */ bcopy((caddr_t)qp->scanmap, (caddr_t)tmpscanlines, sizeof tmpscanlines); /* * Clear the wrapping line so that it won't flash on the bottom * of the screen. */ scanline = qp->scanmap; b_row = qp->bitmap+(*scanline&0x3ff)*128; bzero( b_row, 1920 ); /* * Now move the scanlines down */ bcopy((caddr_t)(qp->scanmap+15), (caddr_t)qp->scanmap, (qp->row * 15) * sizeof (short) ); /* * Now put the other lines back */ bcopy((caddr_t)tmpscanlines, (caddr_t)(qp->scanmap+(qp->row * 15)), sizeof (tmpscanlines) );}/* * Output to the keyboard. This routine status polls the transmitter on the * keyboard to output a code. The timer is to avoid hanging on a bad device. */qv_key_out(c) u_short c;{ int timer = 30000; register struct qv_info *qp = qv_scn; if (qp->qvaddr) { while ((qp->qvaddr->qv_uartstatus & 0x4) == 0 && timer--) ; qp->qvaddr->qv_uartdata = c; }}/* * Virtual console initialization. This routine sets up the qvss so that it can * be used as the system console. It is invoked before autoconfig and has to do * everything necessary to allow the device to serve as the system console. * In this case it must map the q-bus and device areas and initialize the qvss * screen. */qvcons_init(){ struct percpu *pcpu; /* pointer to percpu structure */ register struct qbus *qb; struct qvdevice *qvaddr; /* device pointer */ short *devptr; /* virtual device space */ extern cnputc(); /* standard serial console putc */#define QVSSCSR 017200 /* * If secondary console already configured, * don't override the previous one. */ if (v_putc != cnputc) return 0; /* * find the percpu entry that matches this machine. */ for( pcpu = percpu ; pcpu && pcpu->pc_cputype != cpu ; pcpu++ ) ; if( pcpu == NULL ) return 0; if (pcpu->pc_io->io_type != IO_QBUS) return 0; /* * Found an entry for this cpu. Because this device is Microvax specific * we assume that there is a single q-bus and don't have to worry about * multiple adapters. * * Map the device registers. */ qb = (struct qbus *)pcpu->pc_io->io_details; ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize, UBAIOPAGES * NBPG); /* * See if the qvss is there. */ devptr = (short *)((char *)umem[0] + (qb->qb_memsize * NBPG)); qvaddr = (struct qvdevice *)((u_int)devptr + ubdevreg(QVSSCSR)); if (badaddr((caddr_t)qvaddr, sizeof(short))) return 0; /* * Okay the device is there lets set it up */ if (!qv_setup(qvaddr, 0, 0)) return 0; v_putc = qvputc; consops = &cdevsw[QVSSMAJOR]; return 1;}/* * Do the board specific setup */qv_setup(qvaddr, unit, probed)struct qvdevice *qvaddr;int unit;int probed;{ caddr_t qvssmem; /* pointer to the display mem */ register i; /* simple index */ register struct qv_info *qp; register int *pte; struct percpu *pcpu; /* pointer to percpu structure */ register struct qbus *qb; /* * find the percpu entry that matches this machine. */ for( pcpu = percpu ; pcpu && pcpu->pc_cputype != cpu ; pcpu++ ) ; if( pcpu == NULL ) return(0); /* * Found an entry for this cpu. Because this device is Microvax specific * we assume that there is a single q-bus and don't have to worry about * multiple adapters. * * Map the device memory. */ qb = (struct qbus *)pcpu->pc_io->io_details; i = (u_int)(qvaddr->qv_csr & QV_MEM_BANK) << 7; ioaccess(qb->qb_maddr + i, QVmap[unit], 512 * NBPG); qvssmem = qvmem[unit]; pte = (int *)(QVmap[unit]); for (i=0; i < 512; i++, pte++) *pte = (*pte & ~PG_PROT) | PG_UW | PG_V; qv_scn = (struct qv_info *)((u_int)qvssmem + 251*1024); qp = qv_scn; if( (qvaddr->qv_csr & QV_19INCH) && qv_def_scrn == 0) qv_def_scrn = 1; *qv_scn = qv_scn_defaults[ qv_def_scrn ]; if (probed) qp->qvaddr = qvaddr; qp->bitmap = qvssmem; qp->scanmap = (short *)((u_int)qvssmem + 254*1024); qp->cursorbits = (short *)((u_int)qvssmem + 256*1024-32); /* set up event queue for later */ qp->ibuff = (vsEvent *)qp - QVMAXEVQ; qp->iqsize = QVMAXEVQ; qp->ihead = qp->itail = 0; /* * Setup the crt controller chip. */ for( i=0 ; i<16 ; i++ ) { qvaddr->qv_crtaddr = i; qvaddr->qv_crtdata = qv_crt_parms[ qv_def_scrn ][ i ]; } /* * Setup the display. */ qv_init( qvaddr ); /* * Turn on the video */ qvaddr->qv_csr |= QV_VIDEO_ENA ; return 1;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -