📄 qd.c
字号:
int QBAreg; int bytcnt; int s; int unit; int cookie; int i,j,k; unit = (minor(bp->b_dev) >> 2) & 0x07;/*-----------------* init pointers */ if ((QBAreg = ubasetup(0, bp, 0)) == 0) { mprintf("\nqd%d: qd_strategy: QBA setup error", unit); goto STRAT_ERR; } dga = (struct dga *) qdmap[unit].dga; s = spl5(); qdflags[unit].user_dma = -1; dga->csr |= DMA_IE; cookie = QBAreg & 0x3FFFF; dga->adrs_lo = (short) cookie; dga->adrs_hi = (short) (cookie >> 16); dga->bytcnt_lo = (short) bp->b_bcount; dga->bytcnt_hi = (short) (bp->b_bcount >> 16); while (qdflags[unit].user_dma) { sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR); } splx(s); ubarelse(0, &QBAreg); if (!(dga->csr & DMA_ERR)) { iodone(bp); return; }STRAT_ERR: adder = (struct adder *) qdmap[unit].adder; adder->command = CANCEL; /* cancel adder activity */ dga->csr &= ~DMA_IE; dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ dga->csr |= DMA_ERR; /* clear error condition */ bp->b_flags |= B_ERROR; /* flag an error to physio() */ /* if DMA was running, flush spurious intrpt */ if (dga->bytcnt_lo != 0) { dga->bytcnt_lo = 0; dga->bytcnt_hi = 0; DMA_SETIGNORE(DMAheader[unit]); dga->csr |= DMA_IE; } iodone(bp);} /* qd_strategy *//********************************************************************* qdstart()... startup output to the console screen*********************************************************************** calling convention:** qdstart(tp);* struct tty *tp; ;pointer to tty structure*********/qdstart(tp)register struct tty *tp;{ register int which_unit, unit, c; register struct tty *tp0; int s; int curs_on; struct dga *dga; unit = minor(tp->t_dev); tp0 = &qd_tty[(unit & 0x0FC)+1]; 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, if the alternate console device* is open direct chars there. Drop input from anything but the console* device on the floor. *//* TANDEM is set on the second subchannel for flow control. */ while ( tp->t_outq.c_cc ) { if (unit == 0) { /* console device */ if (tp0->t_state & TS_ISOPEN) { if (tp0->t_state & TS_TBLOCK) goto out; c = getc(&tp->t_outq); (*linesw[tp0->t_line].l_rint)(c, tp0); } else { c = getc(&tp->t_outq); blitc(which_unit, (char)(c & 0xFF)); } } else if (unit == 1) { /* qconsole, do flow control */ c = getc(&tp->t_outq); if ((tp0->t_state&TS_TBLOCK) == 0) { tp = &qd_tty[0]; unit = minor(tp->t_dev); unit &= 0x03; continue; } else goto out; } else c = getc(&tp->t_outq); }/*--------------------------------------------------------* If there are sleepers, and output has drained below low* water mark, wake up the sleepers. */ if ( tp->t_outq.c_cc <= TTLOWAT(tp) ) { 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 *//********************************************************************* qdstop()... stop the tty********************************************************************/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);}/********************************************************************* blitc()... output a character to the QDSS screen*********************************************************************** calling convention:** blitc(chr);* char chr; ;character to be displayed*********/blitc(unit, chr)int unit;unsigned char chr;{ register struct adder *adder; register struct dga *dga; register int i; short x; unsigned char savechar;/*---------------* init stuff */ adder = (struct adder *) qdmap[unit].adder; dga = (struct dga *) qdmap[unit].dga;/*---------------------------* non display character? */ chr &= 0xFF; switch (chr) { case '\r': /* return char */ cursor[unit].x = 0; if (!(qdflags[unit].inuse & GRAPHIC_DEV)) dga->x_cursor = TRANX(cursor[unit].x); return(0); case '\t': /* tab char */ for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) { blitc(unit, ' '); } return(0); case '\n': /* line feed char */ if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) { if (qdflags[unit].inuse & GRAPHIC_DEV) { cursor[unit].y = 0; } else { cursor[unit].y -= CHAR_HEIGHT; scroll_up(adder); } } if (!(qdflags[unit].inuse & GRAPHIC_DEV)) dga->y_cursor = TRANY(cursor[unit].y); return(0); case '\b': /* backspace char */ if (cursor[unit].x > 0) { cursor[unit].x -= CHAR_WIDTH; blitc(unit, ' '); cursor[unit].x -= CHAR_WIDTH; if (!(qdflags[unit].inuse & GRAPHIC_DEV)) dga->x_cursor = TRANX(cursor[unit].x); } return(0); default: /*---------------------------------------------------------- * Weed out unprintable characters. Printable characters fall * between space (0x20) and tilde (0x7E). For 8-bit support * another range of printable characters are those between * 0xA1 and 0xFD. */ if ((chr < ' ') || (chr > 0xFD) || (chr < 0xA1 && chr > '~')) return(0); }/*------------------------------------------* 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; 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 > '~') { savechar = chr; chr -= 34; /* These are to skip the (32) 8-bit control chars. as well as DEL and 0xA0 which aren't printable */ } if ((chr - ' ') > (CHARS - 1)) { mprintf("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 (!(qdflags[unit].inuse & GRAPHIC_DEV)) dga->x_cursor = TRANX(cursor[unit].x); if (cursor[unit].x > (1024 - CHAR_WIDTH)) { blitc(unit, '\r'); blitc(unit, '\n'); }} /* blitc */qdreset(){}qd_init(){}/********************************************************************************************************************************************************************************************************** INTERRUPT SERVICE ROUTINES START HERE:*********************************************************************************************************************************************************************************************************//******************************************************************* qddint()... service "DMA DONE" interrupt condition******************************************************************/qddint(qd)int qd;{ register struct DMAreq_header *header; register struct DMAreq *request; register struct dga *dga; struct adder *adder; int cookie; /* DMA adrs for QDSS */ int i; 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) mprintf("\nqd%d: qddint: DMA hardware parity fault.", qd); if (dga->csr & BUS_ERR) mprintf("\nqd%d: qddint: DMA hardware bus error.", 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 (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) { selwakeup(rsel[qd], 0); rsel[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 (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) { selwakeup(rsel[qd], 0); rsel[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 (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) { selwakeup(rsel[qd], 0); rsel[qd] = 0; qdflags[qd].selmask &= ~SEL_WRITE; } DMA_CLRACTIVE(header); /* fla
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -