/* * flush data in a given address range to memory * and invalidate the region in the instruction cache. */ int segflush(void *a, ulong n) { dcflush(a, n); icflushall(); /* can't be more precise */ return 0; }
int segflush(void *a, ulong n) { /* flush dcache then invalidate icache */ dcflush(a, n); icflush(a, n); return 0; }
void dcrcompile(void) { ulong *p; int i; for(i=0; i<MAXDCR; i++){ p = _getdcr[i]; p[0] = MFDCR(i, 3); p[1] = RETURN; p = _putdcr[i]; p[0] = MTDCR(3, i); p[1] = RETURN; } dcflush(PTR2UINT(_getdcr), sizeof(_getdcr)); dcflush(PTR2UINT(_putdcr), sizeof(_putdcr)); /* no need to flush icache since they won't be there */ }
static void txstart(Ether *ether) { int len; Ctlr *ctlr; Block *b; BD *dre; ctlr = ether->ctlr; if(ctlr->init) return; while(ctlr->ntq < Ntdre-1){ b = qget(ether->oq); if(b == 0) break; dre = &ctlr->tdr[ctlr->tdrh]; dczap(dre, sizeof(BD)); if(dre->status & BDReady) panic("ether: txstart"); /* * Give ownership of the descriptor to the chip, increment the * software ring descriptor pointer and tell the chip to poll. */ len = BLEN(b); if(ctlr->txb[ctlr->tdrh] != nil) panic("fcc/ether: txstart"); ctlr->txb[ctlr->tdrh] = b; if((ulong)b->rp&1) panic("fcc/ether: txstart align"); /* TO DO: ensure alignment */ dre->addr = PADDR(b->rp); dre->length = len; dcflush(b->rp, len); dcflush(dre, sizeof(BD)); dre->status = (dre->status & BDWrap) | BDReady|TxPad|BDInt|BDLast|TxTC; dcflush(dre, sizeof(BD)); /* ctlr->fcc->ftodr = 1<<15; /* transmit now; Don't do this according to errata */ ctlr->ntq++; ctlr->tdrh = NEXT(ctlr->tdrh, Ntdre); } }
/* * return an uncached alias for the memory at a */ void* mmucacheinhib(void *a, ulong nb) { ulong p; if(a == nil) return nil; dcflush(a, nb); p = PADDR(a); return kmapphys((void*)(KSEG1|p), p, nb, TLBWR | TLBI | TLBG, 0); }
/* * initialise receive and transmit buffer rings. */ int ioringinit(Ring* r, int nrdre, int ntdre, int bufsize) { int i, x; /* the ring entries must be aligned on sizeof(BD) boundaries */ r->nrdre = nrdre; if(r->rdr == nil) r->rdr = bdalloc(nrdre); /* the buffer size must align with cache lines since the cache doesn't snoop */ bufsize = (bufsize+CACHELINESZ-1)&~(CACHELINESZ-1); if(r->rrb == nil) r->rrb = malloc(nrdre*bufsize); if(r->rdr == nil || r->rrb == nil) return -1; dcflush(r->rrb, nrdre*bufsize); x = PADDR(r->rrb); for(i = 0; i < nrdre; i++){ r->rdr[i].length = 0; r->rdr[i].addr = x; r->rdr[i].status = BDEmpty|BDInt; x += bufsize; } r->rdr[i-1].status |= BDWrap; r->rdrx = 0; r->ntdre = ntdre; if(r->tdr == nil) r->tdr = bdalloc(ntdre); if(r->txb == nil) r->txb = malloc(ntdre*sizeof(Block*)); if(r->tdr == nil || r->txb == nil) return -1; for(i = 0; i < ntdre; i++){ r->txb[i] = nil; r->tdr[i].addr = 0; r->tdr[i].length = 0; r->tdr[i].status = 0; } r->tdr[i-1].status |= BDWrap; r->tdrh = 0; r->tdri = 0; r->ntq = 0; return 0; }
void main(void) { int machno; /* entry to main pushed stuff onto the stack. */ // memset(edata, 0, (ulong)end-(ulong)edata); machno = getpir(); if (machno > 0) startcpu(machno); // dcrcompile(); if (dverify != 0x01020304) { uartlputs("data segment not initialised\n"); panic("data segment not initialised"); } if (bverify != 0) { uartlputs("bss segment not zeroed\n"); panic("bss segment not zeroed"); } mach0init(); archreset(); quotefmtinstall(); optionsinit("/boot/boot boot"); // archconsole(); meminit(); confinit(); mmuinit(); xinit(); /* xinit would print if it could */ trapinit(); qtminit(); ioinit(); uncinit(); printinit(); uartliteconsole(); mainmem->flags |= POOL_ANTAGONISM; mainmem->panic = mypanic; ethermedium.maxtu = 1512; /* must be multiple of 4 for temac's dma */ // print("\n\nPlan 9k H\n"); /* already printed by l.s */ plan9iniinit(); timersinit(); clockinit(); dma0init(); /* does not start kprocs; see init0 */ fpuinit(); procinit0(); initseg(); links(); chandevreset(); okprint = 1; /* only now can we print */ barriers(); dcflush((uintptr)&okprint, sizeof okprint); cpuidprint(); print("%d Hz clock", HZ); print("; memory size %,ud (%#ux)\n", (uint)memsz, (uint)memsz); pageinit(); swapinit(); userinit(); active.thunderbirdsarego = 1; dcflush((uintptr)&active.thunderbirdsarego, sizeof active.thunderbirdsarego); schedinit(); /* no return */ panic("schedinit returned"); }
static void interrupt(Ureg*, void *arg) { int len, status, rcvd, xmtd, restart; ushort events; Ctlr *ctlr; BD *dre; Block *b, *nb; Ether *ether = arg; ctlr = ether->ctlr; if(!ctlr->active) return; /* not ours */ /* * Acknowledge all interrupts and whine about those that shouldn't * happen. */ events = ctlr->fcc->fcce; ctlr->fcc->fcce = events; /* clear events */ #ifdef DBG ehisto[events & 0x7f]++; #endif ctlr->interrupts++; if(events & BSY) ctlr->overrun++; if(events & TXE) ether->oerrs++; #ifdef DBG rcvd = xmtd = 0; #endif /* * Receiver interrupt: run round the descriptor ring logging * errors and passing valid receive data up to the higher levels * until we encounter a descriptor still owned by the chip. */ if(events & RXF){ dre = &ctlr->rdr[ctlr->rdrx]; dczap(dre, sizeof(BD)); while(((status = dre->status) & BDEmpty) == 0){ rcvd++; if(status & RxError || (status & (BDFirst|BDLast)) != (BDFirst|BDLast)){ if(status & (RxeLG|RxeSH)) ether->buffs++; if(status & RxeNO) ether->frames++; if(status & RxeCR) ether->crcs++; if(status & RxeOV) ether->overflows++; print("eth rx: %ux\n", status); }else{ /* * We have a packet. Read it in. */ len = dre->length-4; b = ctlr->rcvbufs[ctlr->rdrx]; assert(dre->addr == PADDR(b->rp)); dczap(b->rp, len); if(nb = iallocb(Bufsize)){ b->wp += len; etheriq(ether, b, 1); b = nb; b->rp = (uchar*)(((ulong)b->rp + CACHELINESZ-1) & ~(CACHELINESZ-1)); b->wp = b->rp; ctlr->rcvbufs[ctlr->rdrx] = b; ctlr->rdr[ctlr->rdrx].addr = PADDR(b->wp); }else ether->soverflows++; } /* * Finished with this descriptor, reinitialise it, * give it back to the chip, then on to the next... */ dre->length = 0; dre->status = (status & BDWrap) | BDEmpty | BDInt; dcflush(dre, sizeof(BD)); ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre); dre = &ctlr->rdr[ctlr->rdrx]; dczap(dre, sizeof(BD)); } } /* * Transmitter interrupt: handle anything queued for a free descriptor. */ if(events & (TXB|TXE)){ ilock(ctlr); restart = 0; while(ctlr->ntq){ dre = &ctlr->tdr[ctlr->tdri]; dczap(dre, sizeof(BD)); status = dre->status; if(status & BDReady) break; if(status & TxeDEF) ctlr->deferred++; if(status & TxeHB) ctlr->heartbeat++; if(status & TxeLC) ctlr->latecoll++; if(status & TxeRL) ctlr->retrylim++; if(status & TxeUN) ctlr->underrun++; if(status & TxeCSL) ctlr->carrierlost++; if(status & (TxeLC|TxeRL|TxeUN)) restart = 1; ctlr->retrycount += (status>>2)&0xF; b = ctlr->txb[ctlr->tdri]; if(b == nil) panic("fcce/interrupt: bufp"); ctlr->txb[ctlr->tdri] = nil; freeb(b); ctlr->ntq--; ctlr->tdri = NEXT(ctlr->tdri, Ntdre); xmtd++; } if(restart){ ctlr->fcc->gfmr &= ~ENT; delay(10); ctlr->fcc->gfmr |= ENT; cpmop(RestartTx, ctlr->fccid, 0xc); } txstart(ether); iunlock(ctlr); }