📄 scc.c
字号:
IOC_WR(IOC_SIR, ~scc_xerror[line]);}/* * Used to pass mouse (or tablet) reports to the graphics * device driver interrupt service routine. * Entire report passed instead of byte at a time. */struct mouse_report current_rep;u_short pointer_id;#define MOUSE_ID 0x2scc_mkbd_rint(unit) register int unit;{ register struct scc_softc *sc = sccsc; register u_short ch; /* ch is 16 bits long */ register u_short c; struct mouse_report *new_rep; u_short data; register struct scc_reg *rsp; register char ip; /* * If console is a graphics device, * pass keyboard input characters to * its device driver's receive interrupt routine. * Save up complete mouse report and pass it. */ if ((unit <= 1) && vs_gdkint) { new_rep = ¤t_rep; /* mouse report pointer */ rsp = sc->sc_regs[unit]; /* line = mouse or keybd */ SCC_READ(rsp, SCC_RR3, ip); /* read IP bits from RR3A */ while (ip & SCC_RR3_A_RIP) { /* channel A receiver */ c = (rsp->SCC_DATA)>>8; /* read char */ ch = (unit<<8)| c; /* encode line in ch */ if(unit == 0) { /* keyboard char */ (*vs_gdkint)(ch); } else { /* mouse or tablet report */ if (pointer_id == MOUSE_ID) { /* mouse report */ data = ch & 0xff; /* get report byte */ ++new_rep->bytcnt; /* inc report byte count */ if (data & START_FRAME) { /* 1st byte of report? */ new_rep->state = data; if (new_rep->bytcnt > 1) new_rep->bytcnt = 1; /* start new frame */ } else if (new_rep->bytcnt == 2) { /* 2nd byte */ new_rep->dx = data; } else if (new_rep->bytcnt == 3) { /* 3rd byte */ new_rep->dy = data; new_rep->bytcnt = 0; (*vs_gdkint)(0400); /* 400 says line 1 */ } } else { /* tablet report */ data = ch; /* get report byte */ ++new_rep->bytcnt; /* inc report byte count */ if (data & START_FRAME) { /* 1st byte of report? */ new_rep->state = data; if (new_rep->bytcnt > 1) new_rep->bytcnt = 1; /* start new frame */ } else if (new_rep->bytcnt == 2) /* 2nd byte */ new_rep->dx = data & 0x3f; else if (new_rep->bytcnt == 3) /* 3rd byte */ new_rep->dx |= (data & 0x3f) << 6; else if (new_rep->bytcnt == 4) /* 4th byte */ new_rep->dy = data & 0x3f; else if (new_rep->bytcnt == 5){ /* 5th byte */ new_rep->dy |= (data & 0x3f) << 6; new_rep->bytcnt = 0; (*vs_gdkint)(0400); /* 400 says line 1 */ } } } SCC_READ(rsp, SCC_RR3, ip); /* read IP bits again */ } /* while */ } /* if */ }scc_spec_rint(line) register int line;{ scc_dma_rint(line);}scc_dma_rint(unit) register int unit;{ register struct scc_softc *sc = sccsc; register struct tty *tp = &scc_tty[unit]; register u_short c; register int flg; register int status, vector, status0; register int num; register char *endptr; register char *ptr; register struct scc_reg *rsp; register char ip; int overrun = 0; int counter = 0; register int c_mask; IOC_CLR(IOC_SSR, scc_rdma_en[unit]); /* disable rdma */ IOC_WR(IOC_SIR, ~(scc_rint[unit])); /* clear rdma int */ /* compute the offset from the beginning of the page */ /* read rdma ptr */ endptr = (char *)(((sc->ioc_regs[unit]->RDMA_REG) >> 3) & 0xfff); /* add the base of the receive buffer to the endptr */ num = sc->rflag[unit]; /* save flag */ /* pgt - check for boundary crossing */ if (endptr == 0) endptr += (long)(sc->rbuf[unit][num]) + SCC_PAGE_SIZE ; else endptr += (long)(sc->rbuf[unit][num]); endptr -= SCC_WORD; /* move to previous word */ sc->rflag[unit] ^= 1; /* toggle buffer flag */ /* * set rdma ptr to other buffer */ sc->ioc_regs[unit]->RDMA_REG = (u_long)(svtophy(sc->rbuf[unit][sc->rflag[unit]] + SCC_HALF_PAGE - SCC_WORD) << 3); /* unit = comm1 or comm2 */ rsp = sc->sc_regs[scc_other[unit]]; /* channel A */ SCC_READ(rsp, SCC_RR3, ip); /* read IP from RR3A */ if (ip & SCC_RR3_B_RIP) { /* channel B receiver */ rsp = sc->sc_regs[unit]; /* channel B */ SCC_READ(rsp, SCC_RR1, status); /* read status */ rsp->SCC_CMD = (SCC_WR0_ERROR_RESET)<<8; } else { status = 0; } IOC_SET(IOC_SSR, scc_rdma_en[unit]); /* enable rdma */ if ((tp->t_state & TS_ISOPEN) == 0) { wakeup((caddr_t)&tp->t_rawq); return; } flg = tp->t_iflag; ptr = sc->rbuf[unit][num] + SCC_HALF_PAGE - SCC_WORD; /* need to do following because SCC sets unused bits to ones */ switch(tp->t_cflag&CSIZE) { case CS5: c_mask = 0x1f; break; case CS6: c_mask = 0x3f; break; case CS7: c_mask = 0x7f; break; case CS8: c_mask = 0xff; } while (ptr < endptr) { c = ((*(u_short *)ptr)>>8)&c_mask; ptr += SCC_WORD; if (flg & ISTRIP){ c &= 0177; } else { c &= 0377; if ((c == 0377) && (tp->t_line == TERMIODISC) && (flg & PARMRK)) (*linesw[tp->t_line].l_rint)(0377,tp); } (*linesw[tp->t_line].l_rint)(c, tp); } c = ((*(u_short *)ptr)>>8)&c_mask; /* * This code handles the following termio input flags. Also * listed is what the default should be for propper Ultrix * backward compatibility. * * IGNBRK FALSE * BRKINT TRUE * IGNPAR TRUE * PARMRK FALSE * INPCK TRUE * ISTRIP TRUE */ if (status) { /* SCC_FE is interpreted as a break */ if (status & SCC_RR1_FE) { if (do_tpath) { tp->t_tpath |= TP_DOSAK; (*linesw[tp->t_line].l_rint)(c, tp); return; } if (flg & IGNBRK) return; if (flg & BRKINT) { if ((tp->t_lflag_ext & PRAW) && (tp->t_line != TERMIODISC)) c = 0; else { ttyflush(tp, FREAD | FWRITE); gsignal(tp->t_pgrp, SIGINT); return; } } /* * TERMIO: If neither IGNBRK or BRKINT is set, a * break condition is read as a single '\0', * or if PARMRK is set as '\377', '\0' , '\0'. */ else { if (flg & PARMRK){ (*linesw[tp->t_line].l_rint)(0377,tp); (*linesw[tp->t_line].l_rint)(0,tp); } c = 0; } } /* Parity Error */ else if (status & SCC_RR1_PE){ /* * If input parity checking is not enabled, clear out * parity error in this character. */ if ((flg & INPCK) == 0) ; /* don't do anything */ else { if (flg & IGNPAR) return; /* If PARMRK is set, return a character with * framing or parity errors as a 3 character * sequence (0377,0,c). */ if (flg & PARMRK){ (*linesw[tp->t_line].l_rint)(0377,tp); (*linesw[tp->t_line].l_rint)(0,tp); } /* * TERMIO: If neither PARMRK or IGNPAR is set, a * parity error is read as a single '\0'. */ else c = 0; } } /* SVID does not say what to do with overrun errors */ if (status & SCC_RR1_DO) { if(overrun == 0) { printf("scc%d: input silo overflow\n", 0); overrun = 1; } sc->sc_softcnt[unit]++; } } if (flg & ISTRIP){ c &= 0177; } else { c &= 0377; /* * If ISTRIP is not set a valid character of 377 * is read as 0377,0377 to avoid ambiguity with * the PARMARK sequence. */ if ((c == 0377) && (tp->t_line == TERMIODISC) && (flg & PARMRK)) (*linesw[tp->t_line].l_rint)(0377,tp); } (*linesw[tp->t_line].l_rint)(c, tp);}/*ARGSUSED*/sccioctl(dev, cmd, data, flag) dev_t dev; register int cmd; caddr_t data; int flag;{ register struct scc_softc *sc = sccsc; register int unit; register struct tty *tp; register int s; struct uba_device *ui; struct devget *devget; int error; register struct scc_reg *rsp; register int status; register int timo; unit = minor(dev); if((consDev != GRAPHIC_DEV) && (major(dev) == CONSOLEMAJOR) && ((unit&LINEMASK) == 0)) unit |= 3; /* diag console on SLU line 3 */ /* * If there is a graphics device and the ioctl call * is for it, pass the call to the graphics driver. */ if (vs_gdioctl && (unit <= 1)) { return((*vs_gdioctl)(dev, cmd, data, flag)); } tp = &scc_tty[unit]; error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); if (error >= 0) return (error); error = ttioctl(tp, cmd, data, flag); if (error >= 0) { /* * If the call is to set terminal attributes which are * represented in the device's line parameter register then * call the param routine to update the device registers. */ switch(cmd) { case TCSANOW: /* POSIX termios */ case TCSADRAIN: /* POSIX termios */ case TCSAFLUSH: /* POSIX termios */ case TCSETA: /* SVID termio */ case TCSETAW: /* SVID termio */ case TCSETAF: /* SVID termio */ case TIOCSETP: /* Berkeley sgttyb */ case TIOCSETN: /* Berkeley sgttyb */ case TIOCLBIS: /* Berkeley lmode */ case TIOCLBIC: /* Berkeley lmode */ case TIOCLSET: /* Berkeley lmode */ case TIOCLGET: /* Berkeley lmode */ sccparam(unit); break; } return (error); } switch (cmd) { case TIOCSBRK: s = spltty(); rsp = sc->sc_regs[unit]; SCC_READ(rsp, SCC_RR1, status); /* read status */ for(timo=10000; timo > 0; --timo) { if (status & SCC_RR1_ALL_SENT) break; else { SCC_READ(rsp, SCC_RR1, status); } } SCC_SET_BRK(unit); splx(s); break; case TIOCCBRK: s = spltty(); SCC_CLR_BRK(unit); splx(s); break; case TIOCSDTR: (void) sccmctl(dev, DC_DTR | DC_RTS, DMBIS); break; case TIOCCDTR: (void) sccmctl(dev, DC_DTR | DC_RTS, DMBIC); break; case TIOCMSET: (void) sccmctl(dev, dmtoscc(*(int *)data), DMSET); break; case TIOCMBIS: (void) sccmctl(dev, dmtoscc(*(int *)data), DMBIS); break; case TIOCMBIC: (void) sccmctl(dev, dmtoscc(*(int *)data), DMBIC); break; case TIOCMGET: *(int *)data = scctodm(sccmctl(dev, 0, DMGET)); break; case TIOCNMODEM: /* ignore modem status */ /* * By setting the software representation of modem signals * to "on" we fake the system into thinking that this is an * established modem connection. */ s = spltty(); sccsoftCAR |= (1<<(unit&LINEMASK)); if (*(int *)data) /* make mode permanent */ sccdefaultCAR |= (1<<(unit&LINEMASK)); tp->t_state |= TS_CARR_ON; tp->t_cflag |= CLOCAL; /* Map to termio */ SCC_MODEM_OFF(unit); splx(s); break; case TIOCMODEM: s = spltty(); SCC_MODEM_ON(unit); sccsoftCAR &= ~(1<<(unit&LINEMASK)); if (*(int *)data) /* make mode permanent */ sccdefaultCAR &= ~(1<<(unit&LINEMASK)); /* * See if signals necessary for modem connection are present */ if (SCC_XMIT(unit)) { tp->t_state &= ~(TS_ONDELAY); tp->t_state |= TS_CARR_ON; sccspeedi(unit); /* check speed indicate */ sccmodem[unit] = MODEM_CTS|MODEM_CD|MODEM_DSR; } else { tp->t_state &= ~(TS_CARR_ON); sccmodem[unit] &= ~(MODEM_CTS|MODEM_CD|MODEM_DSR); } tp->t_cflag &= ~CLOCAL; /* Map to termio */ splx(s); break; case TIOCWONLINE: /* look at modem status - sleep if no carrier */ s = spltty(); /* * See if signals necessary for modem connection are present */ if (SCC_XMIT(unit)) { tp->t_state |= TS_CARR_ON; sccspeedi(unit); tp->t_state &= ~(TS_ONDELAY); sccmodem[unit] = MODEM_CTS|MODEM_CD|MODEM_DSR; } else { while ((tp->t_state & TS_CARR_ON) == 0) sleep((caddr_t)&tp->t_rawq, TTIPRI); } splx(s); break; case DEVIOCGET: /* device status */ devget = (struct devget *)data; bzero(devget,sizeof(struct devget)); if (tp->t_cflag & CLOCAL) { sc->sc_category_flags[unit&LINEMASK] |= DEV_MODEM; sc->sc_category_flags[unit&LINEMASK] &= ~DEV_MODEM_ON; } else sc->sc_category_flags[unit&LINEMASK] |= (DEV_MODEM|DEV_MODEM_ON); devget->category = DEV_TERMINAL; /* terminal cat.*/ devget->bus = DEV_NB; /* NO bus */ bcopy(DEV_VS_SLU,devget->interface, strlen(DEV_VS_SLU)); /* interface */ bcopy(DEV_UNKNOWN,devget->device, strlen(DEV_UNKNOWN)); /* terminal */ devget->adpt_num = 0; /* NO adapter */ devget->nexus_num = 0; /* fake nexus 0 */ devget->bus_num = 0; /* NO bus */ devget->ctlr_num = 0; /* cntlr number */ devget->slave_num = unit&LINEMASK; /* line number */ bcopy("scc", devget->dev_name, 3); /* Ultrix "scc" */ devget->unit_num = unit&LINEMASK; /* scc line? */ devget->soft_count = sc->sc_softcnt[unit&LINEMASK]; /* soft err cnt */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -