📄 gq.c
字号:
* Although some test runs (heavy imaging) shows this to be true, and * in some cases very true, it shouldn't be. There must be a race * condition we're not handling somewhere... I do know of 1 created by * the pre-pagein code. */ pte = vtopte(gx_serverp, btop(tmpVA)); if (pte && pte->pg_v) { *GQ_INTRH(gqo) = 0; /* clr intr */ wbflush(); /* n10 will retry */ if ((va & HST_INTR_DRTY) == 0) pte->pg_m = 1; /* mark dirty */ return 0; }# endif return _gq_intr_pagein(va);}/* end gq_intr_pagein. */gq_intr_xlate(va) int va;{ register int tmpVA, vsn; register struct pte *pte; tmpVA = (va & HST_INTR_MASK); vsn = vtovsn(tmpVA); /* virt seg num */ GX_DEBUG(GX_BLAB, gx_printf("xlate: vpn 0x%x vsn 0x%x\n", btop(tmpVA), vsn); ); pte = vtopte(gx_serverp, btop(tmpVA)); GX_DEBUG(GX_GAB, gx_printf("xlate: sp 0x%x (0x%x+0x%x) pte 0x%x\n", gx_serverp, gx_serverp->p_datastart, gx_serverp->p_dsize, pte); ); if (pte == 0) { /*GQ_INTRH(gqo) = va; /* clear intr line */ /*wbflush();*/ printf("gq_intr_xlate: bad VA 0x%x\n", tmpVA); /* let server segv while handling signal */ return _gq_intr_pagein(va); } gq_ptpt[vsn] = (int) svtophy((int)pte & ~(NBPG-1)) | vsn; GX_DEBUG(GX_GAB, gx_printf("gq_intr_xlate(va=0x%x) -> ptpt[0x%x]=0x%x\n", tmpVA, vsn, gq_ptpt[vsn]); ); if (pte->pg_v) { /* page is already valid */ *GQ_INTRH(gqo) = (pte->pg_pfnum << GQ_INTR_SHFT); wbflush(); return 0; } else { /* request pagein */ return _gq_intr_pagein(va); }}/* end gq_intr_xlate. */gq_intr_vrfy(va) int va;{ register int tmpVA; register struct pte *pte; tmpVA = (va & HST_INTR_MASK); pte = vtopte(gx_serverp, btop(tmpVA)); if (pte == 0) { /*GQ_INTRH(gqo) = va; /* clear intr line */ /*wbflush();*/ printf("gq_intr_vrfy: bad VA 0x%x\n", tmpVA); /* let server segv while handling signal */ return _gq_intr_pagein(va); } if (pte->pg_v) { /* page is already valid */ *GQ_INTRH(gqo) = (pte->pg_pfnum << GQ_INTR_SHFT); wbflush(); return 0; } else { *GQ_INTRH(gqo) = GQ_INTR_ACK; /* N10 will choke on this */ wbflush(); GX_DEBUG(GX_CONSOLE, gq_thrash++; gx_printf("gq_intr_vrfy: bad pte 0x%x (VA 0x%x)\n", pte, tmpVA); ); gx_serverp->p_dev_VM_maint = 0; psignal(gx_serverp, SIGSEGV); /* not valid - SEGV the server */ }}/* end gq_intr_vrfy. *//****************************************************************** ** ** ** Graphics device end-of-frame interrupt service routine. ** ** ** ****************************************************************** * * For the HE3D 3MAX board, N10 receives VINT. VINT is normally off. * When an N10 packet with the sync bit arrives at the head of the * packet queue, N10 enables VINT and interrupts R3 when STIC interrupts * N10 for VINT. We load the colormap during this time. Unused. */gq_intr_vblank(va) int va;{ *GQ_INTRH(gqo) = GQ_INTR_ACK; wbflush(); GX_DEBUG(GX_BLAB, gx_puts("gq_intr_vblank()\n"); ); gx_load_colormap(); gxp->qe.timestamp_ms = TOY; return 0;}/* end gq_intr_vblank. */int gq_intr_total = 0;gqintr(unit) register int unit;{ gq_intr_total++; if (GX_HAVESERVER) { int intr_cause = GQ_RAM(gqo)->intr_host; /* XXX byte-0 assumed. */ (gq_intr_recv[intr_cause & HST_INTR_WHAT])++; return (*gq_intr_vec[intr_cause & HST_INTR_WHAT])(intr_cause); } else { /* could also be a STIC error intr... */ return gq_intr_stic(); }}/* end gqintr. */gq_intr_coproc(cmd) int cmd;{ register int i, ans; volatile int *intr_coproc = GQ_INTRC(gqo); volatile int *read_coproc = &(GQ_RAM(gqo)->intr_coproc); int rval = 4; int timo = gq_N1OK ? GQ_INTR_TIMO : (GQ_INTR_TIMO >> 2); GX_DEBUG(GX_SILENT, if (gq_intrPending) { /* nested interrupts invalid */ printf("gq_intr_coproc: new 0x%x (old 0x%x)\n", cmd, *read_coproc); panic("gq_intr_coproc: nested\n"); } gq_intrPending = 1; ); GX_DEBUG(GX_NEVER, gx_printf("gq_intr_coproc(cmd=0x%x)\n", cmd); ); *intr_coproc = cmd; wbflush(); gq_intr_send[(cmd & GQ_INTR_WHAT) >> GQ_INTR_WSHF]++; for ( i = timo; i > 0; i-- ) { DELAY(2); /* 150 cycles for N10 intr roundtrip */ switch (ans = *read_coproc) /* N10 running at 25-30ns clock */ { case 0xdeadbabe: case 0x00000000: GX_DEBUG(GX_SILENT, gq_intrPending = 0;); return -1; case GQ_INTR_BUF0: /* 1 */ GX_DEBUG(GX_SILENT, gq_intrPending = 0;); return 0; case GQ_INTR_BUF1: /* 2 */ GX_DEBUG(GX_SILENT, gq_intrPending = 0;); return 1; default: if (ans != cmd) { GX_DEBUG(GX_CONSOLE, gx_printf("gq_intr_coproc: 0x%x bad repl=0x%x\n", cmd, ans); ); rval = 2; /* > 1 */ goto BadReply; } } } GX_DEBUG(GX_CONSOLE, gx_printf("gq_intr_coproc: 0x%x dead=0x%x spl %d hst 0x%x\n", cmd, ans, whatspl(), GQ_RAM(gqo)->intr_host); ); BadReply: if (gq_debug & GQ_KILL_N10) { if (GX_HAVESERVER)# ifdef p_dev_VM_maint gx_serverp->p_dev_VM_maint = 0;# endif psignal(gx_serverp,SIGILL); /* kill the server */ *GQ_RESET(gqo) = 0; /* kill the N10 */ wbflush(); } else {# ifdef p_dev_VM_maint if (GX_HAVESERVER) gx_serverp->p_dev_VM_maint = 0;# endif } GX_DEBUG(GX_SILENT, gq_intrPending = 0;); gq_N1OK = 0; return rval;}/* end gq_intr_coproc. */gq_vm_hook(cmd, vpn) /* alias p_dev_VM_maint */ int cmd, vpn;{ int vsn; if (GX_HAVESERVER) { int reply; vpn = (int)ptob(vpn) & GQ_INTR_MASK; /* now va, page aligned */ GX_DEBUG(GX_SILENT, gq_invalALL++;); switch (cmd) { case PDEVCMD_ONE: GX_DEBUG(GX_NEVER, gx_printf("gq_vm_hook(cmd=1,vpn=0x%x)\n", vpn); ); reply = gq_intr_coproc(vpn | GQ_INTR_INV1); GX_DEBUG(GX_CONSOLE, char *msg; int *pTLB; switch (reply) { case 2: msg = "REP"; break; case 3: msg = "STO"; break; case 4: msg = "LTO"; break; default:msg = "OK"; } pTLB = (int *)((int)GQ_RAM(gqo) + N10_VTLB_OFF); if (pTLB[GQ_VTLB_INDEX(vpn)] == 0 || (pTLB[GQ_VTLB_INDEX(vpn)] & 0xfffff) == 0xbabed) { gq_invalOK++; } else { gx_printf("gq_vm_hook: 0x%x[0x%x] -> 0x%x %s 0x%x\n", vpn, GQ_VTLB_INDEX(vpn), pTLB[GQ_VTLB_INDEX(vpn)], msg, GQ_RAM(gqo)->intr_coproc); } ); break; case PDEVCMD_ALL: GX_DEBUG(GX_NEVER, gx_printf("gq_vm_hook(cmd=a,vpn=0x%x)\n", vpn); ); bzero(gq_ptpt, GQ_PTPT_SIZE); if (gq_intr_coproc(GQ_INTR_INVA) >= 0) printf("gq_vm_hook: INVA\n"); break; case PDEVCMD_TOP: vsn = vtovsn(vpn); GX_DEBUG(GX_NEVER, gx_printf("gq_vm_hook(cmd=t,vpn=0x%x:vsn=0x%x)\n", vpn, vsn); ); /* I'm assuming that we dont get called here (brk(2) with * * change < 0) except when a page table page is freed. */ bzero(gq_ptpt + vsn, GQ_PTPT_SIZE - vsn); if (gq_intr_coproc(vpn | GQ_INTR_CEIL) >= 0) printf("gq_vm_hook: CEIL\n"); break; default: GX_DEBUG(GX_GAB, gx_printf("gq_vm_hook(cmd=bad 0x%x)\n", cmd); ); printf("gq_vm_hook: bad cmd 0x%x\n", cmd); panic("gq_vm_hook"); } } else printf("gq_vm_hook: no server?\n"); return 0;}/* end gq_vm_hook. */voidgq_cpu_idleSample(arg) char *arg;{ if (gq_N1OK) { register struct cpudata *pcpu=CURRENT_CPUDATA; gx_info.host_idle = pcpu->cpu_cptime[CP_IDLE]; gx_info.host_idleCount++; timeout(gq_cpu_idleSample, (char *)0, GQ_CPU_IDLESAMPLE); }}/* end gq_cpu_idleSample. */gq_close(dev, flag){# ifdef p_dev_VM_maint /* unexpress interest in server's vm activity... */ if (GX_HAVESERVER) { gx_serverp->p_dev_VM_maint = 0; *GQ_RESET(gqo) = gq_N1OK = 0; /* halt N10 */ wbflush(); GX_DEBUG(GX_GAB, gx_printf("gq_close: pid=%d\n", gx_serverp->p_pid); ); }# endif return 0;}/* end gq_close. */gq_config(qp, module_type) register gxInfo *qp; int module_type;{ qp->gxo = (char *)gqo; qp->gram = (int *)GQ_RAM(gqo); if (module_type == STIC_OPT_2DA) { printf("gq_config: not 3DA, STIC modtype = %d\n", module_type); panic("gq_config"); } return 0;}/* end gq_config. */gq_getPixBuff(p_sva, p_stic) int **p_sva; /* sys virt addr */ int *p_stic; /* stic phys addr */{ u_long sram_addr; *p_sva = GQ_RAM(gqo)->pixbuf; /* K1 addr */ sram_addr = GQ_SYS_TO_PHYS(*p_sva); *p_stic = GX_SYS_TO_STIC(sram_addr);}int *gq_getPacket(){ static int whichBuffer = 0; /* 0 || 1 */ register int *buf; /* * don't collide with N10 over SRAM when xcons not enabled! * should not be the common case. */ if (gq_N1OK) { register int i; /* ask N10 which packet buffer */ /* we may use. */ whichBuffer = gq_intr_coproc(GQ_INTR_PAUS); if (whichBuffer < 0 || whichBuffer > 1) { GX_DEBUG(GX_TERSE, gx_printf("gq_getPacket: bad reply from i860 %d\n", whichBuffer); ); return ((int *)(whichBuffer = 0)); } GX_DEBUG(GX_GAB, gx_printf("gq_getPacket: i860->%d\n", whichBuffer); ); _POLL_STIC_PINT(i); /* then wait for stic to be idle */ } /* since this buffer may be currently */ /* executing */ buf = GQ_REQBUF(gqo, whichBuffer); whichBuffer ^= 0x1; return (buf);}/* end gq_getPacket. */gq_sendPacket(buf) char *buf; /* virtual addr */{ int i, addr; volatile int *poll; /* ... to sram phys addr ... */ addr = GQ_SYS_TO_PHYS(buf); poll = (int *)((char *)GQ_POLL(gqo) + GX_SYS_TO_DMA(addr)); _POLL_STIC_PINT(i); _gx_stic->ipdvint = STIC_INT_P_WE; /* clear pkt done intr bit */ wbflush(); /* make sure all writes completed */ if (*poll != STAMP_GOOD) { gx_init_stic(); gx_unwedge_stic++; if (*poll != STAMP_GOOD) { gx_dropped_packet++; GX_DEBUG(GX_TERSE, gx_printf("STIC:CSR 0x%x B:SR 0x%x A 0x%x D 0x%x I 0x%x\n", _gx_stic->sticsr, _gx_stic->buscsr, _gx_stic->busadr, _gx_stic->busdat, _gx_stic->ipdvint); ); return -1; } } /* if N10 running, then must have */ if (gq_N1OK) { /* asked permission to do console */ register int k; /* output, so N10 must be waiting */ _POLL_STIC_PINT(k); /* for OK to proceed... */ GQ_RAM(gqo)->intr_coproc = 0; wbflush(); } return (i);}/* end gq_sendPacket. *//* * THE BEGINNING. */gq_cons_init(){ register int reg; int tmp1; extern int cpu, console_magic; if (cpu == DS_3100) return (0); reg = tc_where_option("gq"); if (reg == 0) return (0); reg = PHYS_TO_K1(reg); /* * 3max console ROM changes for enhanced TURBOchannel support * have eliminated the ability to have multiple outputs. If * new ROM is in place, use the output device specifiec by ROM. */ if (console_magic != 0x30464354) { tmp1 = atoi(prom_getenv("osconsole")); if (tmp1 & 0x1) gx_console |= GRAPHIC_DEV; if (tmp1 & 0x8) gx_console |= CONS_DEV; } else { tmp1 = rex_getenv("osconsole"); if (strlen(tmp1) > 1) { if (tmp1 & 0x1) gx_console = GRAPHIC_DEV; } else { if (tmp1 & 0x8) gx_console = CONS_DEV; } } GX_DEBUG(GX_GAB, gx_printf("gq_cons_init: reg=0x%x\n", reg); ); gqo = (gqMap *)reg; /* K1 physaddr: base of option board */ /* * KM_ALLOC storage area for gxPriv struct. This has to be done * here, since the console code assumes gx_priv exists already! */ KM_ALLOC(gx_priv, gxPriv *, GQ_PRIV_SIZE, KM_DEVBUF, KM_CLEAR|KM_CONTIG); if (!gx_priv) return 0; gx_priv = (gxPriv *)PHYS_TO_K0(svtophy(gx_priv)); /* * ditto for the ((page table page) table) ... */ KM_ALLOC(gq_ptpt, int *, GQ_PTPT_SIZE, KM_DEVBUF, KM_CLEAR|KM_CONTIG); if (!gq_ptpt) return 0; gq_ptpt = (int *)PHYS_TO_K1(svtophy(gq_ptpt)); gxp = &(gx_info); gx_rboffset = sizeof(gxPriv)/sizeof(int); /* * Required linkage... */ _gx_vdac = GQ_VDAC(gqo); _gx_vdacReset = GQ_VDACRESET(gqo); _gx_stamp = GQ_STAMP(gqo); /* stic stamp space @ 0x..0c0000 */ _gx_stic = GQ_STIC(gqo); /* stic register space @ 0x..180000 */ _gx_modtype = ((_gx_stic->modcl & ~STIC_CF_CONFIG_OPTION) | STIC_OPT_3DA_SH); _gx_config = gq_config; _gx_ioctl = gq_ioctl; _gx_getPacket = gq_getPacket; _gx_sendPacket = gq_sendPacket; _gx_getPixBuff = gq_getPixBuff; /* * Optional linkage... */ _gx_init = gq_init; _gx_close = gq_close; gq_init_cons(); return (1);}/* end gq_cons_init. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -