📄 qd.c
字号:
register which_unit, unit, c; int s; unit = minor(tp->t_dev); which_unit = (unit >> 2) & 0x3; unit &= 0x03; 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. * Drop input from anything but the console * device on the floor. * * XXX - this loop is done at spltty. * */ while (tp->t_outq.c_cc) { c = getc(&tp->t_outq); if (unit == 0) blitc(which_unit, (u_char)c); } /* * 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);} /* qdstart *//*ARGSUSED*/qdstop(tp, flag) register struct tty *tp; int flag;{ register int s; s = spl5(); /* block intrpts during state modification */ 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);}/* * Output a character to the QDSS screen */blitc(unit, chr) register unit; register u_char chr;{ register struct adder *adder; register struct dga *dga; register int i; int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV); static short inescape[NQD]; adder = (struct adder *)qdmap[unit].adder; dga = (struct dga *) qdmap[unit].dga; /* * BSD comment: this (&=0177) defeats the extended character * set code for the glass tty, but if i had the time i would * spend it ripping out the code completely. This driver * is too big for its own good. */ chr &= 0177; /* * Cursor addressing (so vi will work). * Decode for "\E=%.%." cursor motion description. * Corresponds to type "qdcons" in /etc/termcap: * * qd|qdss|qdcons|qdss glass tty (4.4 BSD):\ * :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K: * */ if (inescape[unit] && nograph) { switch (inescape[unit]++) { case 1: if (chr != '=') { /* abort escape sequence */ inescape[unit] = 0; blitc(unit, chr); } return; case 2: /* position row */ cursor[unit].y = CHAR_HEIGHT * chr; if (cursor[unit].y > 863 - CHAR_HEIGHT) cursor[unit].y = 863 - CHAR_HEIGHT; dga->y_cursor = TRANY(cursor[unit].y); return; case 3: /* position column */ cursor[unit].x = CHAR_WIDTH * chr; if (cursor[unit].x > 1024 - CHAR_WIDTH) cursor[unit].x = 1023 - CHAR_WIDTH; dga->x_cursor = TRANX(cursor[unit].x); inescape[unit] = 0; return; default: inescape[unit] = 0; blitc(unit, chr); } } switch (chr) { case '\r': /* return char */ cursor[unit].x = 0; if (nograph) dga->x_cursor = TRANX(cursor[unit].x); return; case '\t': /* tab char */ for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) { blitc(unit, ' '); } return; case '\n': /* line feed char */ if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) { if (nograph) { cursor[unit].y -= CHAR_HEIGHT; scroll_up(adder); } else cursor[unit].y = 0; } if (nograph) dga->y_cursor = TRANY(cursor[unit].y); return; case '\b': /* backspace char */ if (cursor[unit].x > 0) { cursor[unit].x -= CHAR_WIDTH; if (nograph) dga->x_cursor = TRANX(cursor[unit].x); } return; case CTRL('k'): /* cursor up */ if (nograph && cursor[unit].y > 0) { cursor[unit].y -= CHAR_HEIGHT; dga->y_cursor = TRANY(cursor[unit].y); } return; case CTRL('^'): /* home cursor */ if (nograph) { cursor[unit].x = 0; dga->x_cursor = TRANX(cursor[unit].x); cursor[unit].y = 0; dga->y_cursor = TRANY(cursor[unit].y); } return; case CTRL('l'): /* cursor right */ if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) { cursor[unit].x += CHAR_WIDTH; dga->x_cursor = TRANX(cursor[unit].x); } return; case CTRL('z'): /* clear screen */ if (nograph) { setup_dragon(unit); clear_qd_screen(unit); /* home cursor - termcap seems to assume this */ cursor[unit].x = 0; dga->x_cursor = TRANX(cursor[unit].x); cursor[unit].y = 0; dga->y_cursor = TRANY(cursor[unit].y); } return; case '\033': /* start escape sequence */ if (nograph) inescape[unit] = 1; return; default: if ((chr < ' ') || (chr > '~')) return; } /* * setup VIPER operand control registers */ write_ID(adder, CS_UPDATE_MASK, 0x0001); /* select plane #0 */ write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); write_ID(adder, CS_UPDATE_MASK, 0x00FE); /* select other planes */ write_ID(adder, SRC1_OCR_B, EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY); write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); write_ID(adder, MASK_1, 0xFFFF); write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1); write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); adder->x_clip_min = 0; adder->x_clip_max = 1024; adder->y_clip_min = 0; adder->y_clip_max = 864; /* * load DESTINATION origin and vectors */ adder->fast_dest_dy = 0; adder->slow_dest_dx = 0; adder->error_1 = 0; adder->error_2 = 0; adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; (void)wait_status(adder, RASTEROP_COMPLETE); adder->destination_x = cursor[unit].x; adder->fast_dest_dx = CHAR_WIDTH; adder->destination_y = cursor[unit].y; adder->slow_dest_dy = CHAR_HEIGHT; /* * load SOURCE origin and vectors */ if ((chr - ' ') > (CHARS - 1)) { printf("Invalid character (x)%x in blitc\n",chr); chr = ' '; } /* * X position is modulo the number of characters per line */ adder->source_1_x = FONT_X + (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH); /* * Point to either first or second row */ adder->source_1_y = 2048 - 15 * (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1); adder->source_1_dx = CHAR_WIDTH; adder->source_1_dy = CHAR_HEIGHT; write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; /* * update console cursor coordinates */ cursor[unit].x += CHAR_WIDTH; if (nograph) dga->x_cursor = TRANX(cursor[unit].x); if (cursor[unit].x > (1024 - CHAR_WIDTH)) { blitc(unit, '\r'); blitc(unit, '\n'); }} /* blitc */qdreset() { }/* * INTERRUPT SERVICE ROUTINES *//* * Service "DMA DONE" interrupt condition */qddint(qd) register qd;{ register struct DMAreq_header *header; register struct DMAreq *request; register struct dga *dga; struct adder *adder; int cookie; /* DMA adrs for QDSS */ (void)spl4(); /* allow interval timer in */ /* * init pointers */ header = DMAheader[qd]; /* register for optimization */ dga = (struct dga *) qdmap[qd].dga; adder = (struct adder *) qdmap[qd].adder; /* * if this interrupt flagged as bogus for interrupt flushing purposes.. */ if (DMA_ISIGNORE(header)) { DMA_CLRIGNORE(header); return; } /* * dump a DMA hardware error message if appropriate */ if (dga->csr & DMA_ERR) { if (dga->csr & PARITY_ERR) printf("qd%d: qddint: DMA hardware parity fault.\n", qd); if (dga->csr & BUS_ERR) printf("qd%d: qddint: DMA hardware bus error.\n", qd); } /* * if this was a DMA from user space... */ if (qdflags[qd].user_dma) { qdflags[qd].user_dma = 0; wakeup((caddr_t)&qdflags[qd].user_dma); return; } /* * if we're doing DMA request queue services, field the error condition */ if (dga->csr & DMA_ERR) { dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ dga->csr |= DMA_ERR; /* clear error condition */ adder->command = CANCEL; /* cancel adder activity */ DMA_SETERROR(header); /* flag error in header status word */ DMA_CLRACTIVE(header); header->DMAreq[header->oldest].DMAdone |= HARD_ERROR; header->newest = header->oldest; header->used = 0; if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { selwakeup(qdrsel[qd], 0); qdrsel[qd] = 0; qdflags[qd].selmask &= ~SEL_WRITE; } if (dga->bytcnt_lo != 0) { dga->bytcnt_lo = 0; dga->bytcnt_hi = 0; DMA_SETIGNORE(header); } return; } /* * if the DMA request queue is now becoming non-full, * wakeup "select" client. */ if (DMA_ISFULL(header)) { if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { selwakeup(qdrsel[qd], 0); qdrsel[qd] = 0; qdflags[qd].selmask &= ~SEL_WRITE; } } header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE; QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype; /* check for unexpected interrupt */ if (DMA_ISEMPTY(header)) return; DMA_GETEND(header); /* update request queue indices */ /* * if no more DMA pending, wake up "select" client and exit */ if (DMA_ISEMPTY(header)) { if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { selwakeup(qdrsel[qd], 0); qdrsel[qd] = 0; qdflags[qd].selmask &= ~SEL_WRITE; } DMA_CLRACTIVE(header); /* flag DMA done */ return; } /* * initiate next DMA xfer */ request = DMA_GETBEGIN(header); if (request->DMAtype != QDlast_DMAtype) { dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ adder->command = CANCEL; /* cancel adder activity */ } switch (request->DMAtype) { case DISPLIST: if (request->DMAtype != QDlast_DMAtype) { dga->csr |= DL_ENB; dga->csr &= ~(BTOP_ENB | BYTE_DMA); } break; case PTOB: if (request->DMAtype != QDlast_DMAtype) { if (request->DMAdone & BYTE_PACK) dga->csr |= (PTOB_ENB | BYTE_DMA); else { dga->csr |= PTOB_ENB; dga->csr &= ~BYTE_DMA; } } break; case BTOP: if (request->DMAtype != QDlast_DMAtype) { if (request->DMAdone & BYTE_PACK) { dga->csr &= ~DL_ENB; dga->csr |= (BTOP_ENB | BYTE_DMA); } else { dga->csr |= BTOP_ENB; dga->csr &= ~(BYTE_DMA | DL_ENB); } } break; default: printf("qd%d: qddint: illegal DMAtype parameter.\n", qd); DMA_CLRACTIVE(header); /* flag DMA done */ return; } if (request->DMAdone & COUNT_ZERO) { dga->csr &= ~SET_DONE_FIFO; } else if (request->DMAdone & FIFO_EMPTY) { dga->csr |= SET_DONE_FIFO; } if (request->DMAdone & WORD_PACK) dga->csr &= ~BYTE_DMA; else if (request->DMAdone & BYTE_PACK) dga->csr |= BYTE_DMA; dga->csr |= DMA_IE; QDlast_DMAtype = request->DMAtype; cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg; dga->adrs_lo = (short) cookie; dga->adrs_hi = (short) (cookie >> 16); dga->bytcnt_lo = (short) request->length; dga->bytcnt_hi = (short) (request->length >> 16); return;}/* * ADDER interrupt service routine */qdaint(qd) register qd;{ register struct adder *adder; struct color_buf *cbuf; int i; register struct rgb *rgbp; register short *red; register short *green; register short *blue; (void)spl4(); /* allow interval timer in */ adder = (struct adder *) qdmap[qd].adder; /* * service the vertical blank interrupt (VSYNC bit) by loading * any pending color map load request */ if (adder->status & VSYNC) { adder->status &= ~VSYNC; /* clear the interrupt */ cbuf = color_buf[qd]; if (cbuf->status & LOAD_COLOR_MAP) { red = (short *) qdmap[qd].red; green = (short *) qdmap[qd].green; blue = (short *) qdmap[qd].blue; for (i = cbuf->count, rgbp = cbuf->rgb; --i >= 0; rgbp++) { red[rgbp->offset] = (short) rgbp->red; green[rgbp->offset] = (short) rgbp->green; blue[rgbp->offset] = (short) rgbp->blue; } cbuf->status &= ~LOAD_COLOR_MAP; } } /* * service the scroll interrupt (FRAME_SYNC bit) */ if (adder->status & FRAME_SYNC) { adder->status &= ~FRAME_SYNC; /* clear the interrupt */ if (scroll[qd]->status & LOAD_REGS) { for (i = 1000, adder->status = 0; i > 0 &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -