⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 etherfcc.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	else		fccthisto[xmtd]++;	if(xmtd)		fccrthisto[rcvd]++;	else		fccrhisto[rcvd]++;#endif}static longifstat(Ether* ether, void* a, long n, ulong offset){	char *p;	int len, i, r;	Ctlr *ctlr;	MiiPhy *phy;	if(n == 0)		return 0;	ctlr = ether->ctlr;	p = malloc(2*READSTR);	len = snprint(p, 2*READSTR, "interrupts: %lud\n", ctlr->interrupts);	len += snprint(p+len, 2*READSTR-len, "carrierlost: %lud\n", ctlr->carrierlost);	len += snprint(p+len, 2*READSTR-len, "heartbeat: %lud\n", ctlr->heartbeat);	len += snprint(p+len, 2*READSTR-len, "retrylimit: %lud\n", ctlr->retrylim);	len += snprint(p+len, 2*READSTR-len, "retrycount: %lud\n", ctlr->retrycount);	len += snprint(p+len, 2*READSTR-len, "latecollisions: %lud\n", ctlr->latecoll);	len += snprint(p+len, 2*READSTR-len, "rxoverruns: %lud\n", ctlr->overrun);	len += snprint(p+len, 2*READSTR-len, "txunderruns: %lud\n", ctlr->underrun);	len += snprint(p+len, 2*READSTR-len, "framesdeferred: %lud\n", ctlr->deferred);	miistatus(ctlr->mii);	phy = ctlr->mii->curphy;	len += snprint(p+len, 2*READSTR-len, "phy: link=%d, tfc=%d, rfc=%d, speed=%d, fd=%d\n",		phy->link, phy->tfc, phy->rfc, phy->speed, phy->fd);#ifdef DBG	if(ctlr->mii != nil && ctlr->mii->curphy != nil){		len += snprint(p+len, 2*READSTR, "phy:   ");		for(i = 0; i < NMiiPhyr; i++){			if(i && ((i & 0x07) == 0))				len += snprint(p+len, 2*READSTR-len, "\n       ");			r = miimir(ctlr->mii, i);			len += snprint(p+len, 2*READSTR-len, " %4.4uX", r);		}		snprint(p+len, 2*READSTR-len, "\n");	}#endif	snprint(p+len, 2*READSTR-len, "\n");	n = readstr(offset, a, n, p);	free(p);	return n;}/* * This follows the MPC8260 user guide: section28.9's initialisation sequence. */static intfccsetup(Ctlr *ctlr, FCC *fcc, uchar *ea){	int i;	Etherparam *p;	MiiPhy *phy;	/* Turn Ethernet off */	fcc->gfmr &= ~(ENR | ENT);	ioplock();	switch(ctlr->port) {	default:		iopunlock();		return -1;	case 0:		/* Step 1 (Section 28.9), write the parallel ports */		ctlr->pmdio = 0x01000000;		ctlr->pmdck = 0x08000000;		imm->port[0].pdir &= ~A1dir0;		imm->port[0].pdir |= A1dir1;		imm->port[0].psor &= ~A1psor0;		imm->port[0].psor |= A1psor1;		imm->port[0].ppar |= (A1dir0 | A1dir1);		/* Step 2, Port C clocks */		imm->port[2].psor &= ~0x00000c00;		imm->port[2].pdir &= ~0x00000c00;		imm->port[2].ppar |= 0x00000c00;		imm->port[3].pdat |= (ctlr->pmdio | ctlr->pmdck);		imm->port[3].podr |= ctlr->pmdio;		imm->port[3].pdir |= (ctlr->pmdio | ctlr->pmdck);		imm->port[3].ppar &= ~(ctlr->pmdio | ctlr->pmdck);		eieio();		/* Step 3, Serial Interface clock routing */		imm->cmxfcr &= ~0xff000000;	/* Clock mask */		imm->cmxfcr |= 0x37000000;	/* Clock route */		break;	case 1:		/* Step 1 (Section 28.9), write the parallel ports */		ctlr->pmdio = 0x00400000;		ctlr->pmdck = 0x00200000;		imm->port[1].pdir &= ~B2dir0;		imm->port[1].pdir |= B2dir1;		imm->port[1].psor &= ~B2psor0;		imm->port[1].psor |= B2psor1;		imm->port[1].ppar |= (B2dir0 | B2dir1);		/* Step 2, Port C clocks */		imm->port[2].psor &= ~0x00003000;		imm->port[2].pdir &= ~0x00003000;		imm->port[2].ppar |= 0x00003000;		imm->port[2].pdat |= (ctlr->pmdio | ctlr->pmdck);		imm->port[2].podr |= ctlr->pmdio;		imm->port[2].pdir |= (ctlr->pmdio | ctlr->pmdck);		imm->port[2].ppar &= ~(ctlr->pmdio | ctlr->pmdck);		eieio();		/* Step 3, Serial Interface clock routing */		imm->cmxfcr &= ~0x00ff0000;		imm->cmxfcr |= 0x00250000;		break;	case 2:		/* Step 1 (Section 28.9), write the parallel ports */		imm->port[1].pdir &= ~B3dir0;		imm->port[1].pdir |= B3dir1;		imm->port[1].psor &= ~B3psor0;		imm->port[1].psor |= B3psor1;		imm->port[1].ppar |= (B3dir0 | B3dir1);		/* Step 2, Port C clocks */		imm->port[2].psor &= ~0x0000c000;		imm->port[2].pdir &= ~0x0000c000;		imm->port[2].ppar |= 0x0000c000;		imm->port[3].pdat |= (ctlr->pmdio | ctlr->pmdck);		imm->port[3].podr |= ctlr->pmdio;		imm->port[3].pdir |= (ctlr->pmdio | ctlr->pmdck);		imm->port[3].ppar &= ~(ctlr->pmdio | ctlr->pmdck);		eieio();		/* Step 3, Serial Interface clock routing */		imm->cmxfcr &= ~0x0000ff00;		imm->cmxfcr |= 0x00003700;		break;	}	iopunlock();	p = (Etherparam*)(m->immr->prmfcc + ctlr->port);	memset(p, 0, sizeof(Etherparam));	/* Step 4 */	fcc->gfmr |= ENET;	/* Step 5 */	fcc->fpsmr = CRCE | FDE | LPB;	/* full duplex operation */	ctlr->duplex = ~0;	/* Step 6 */	fcc->fdsr = 0xd555;	/* Step 7, initialize parameter ram */	p->rbase = PADDR(ctlr->rdr);	p->tbase = PADDR(ctlr->tdr);	p->rstate = (GBL | EB) << 24;	p->tstate = (GBL | EB) << 24;	p->cmask = 0xdebb20e3;	p->cpres = 0xffffffff;	p->retlim = 15;	/* retry limit */	p->mrblr = (Rbsize+0x1f)&~0x1f;		/* multiple of 32 */	p->mflr = Rbsize;	p->minflr = ETHERMINTU;	p->maxd1 = (Rbsize+7) & ~7;	p->maxd2 = (Rbsize+7) & ~7;	for(i=0; i<Eaddrlen; i+=2)		p->paddr[2-i/2] = (ea[i+1]<<8)|ea[i];	/* Step 7, initialize parameter ram, configuration-dependent values */	p->riptr = m->immr->fccextra[ctlr->port].ri - (uchar*)IMMR;	p->tiptr = m->immr->fccextra[ctlr->port].ti - (uchar*)IMMR;	p->padptr = m->immr->fccextra[ctlr->port].pad - (uchar*)IMMR;	memset(m->immr->fccextra[ctlr->port].pad, 0x88, 0x20);	/* Step 8, clear out events */	fcc->fcce = ~0;	/* Step 9, Interrupt enable */	fcc->fccm = TXE | RXF | TXB;	/* Step 10, Configure interrupt priority (not done here) */	/* Step 11, Clear out current events */	/* Step 12, Enable interrupts to the CP interrupt controller */	/* Step 13, Issue the Init Tx and Rx command, specifying 0xc for ethernet*/	cpmop(InitRxTx, fccid[ctlr->port], 0xc);	/* Step 14, Link management */	if((ctlr->mii = malloc(sizeof(Mii))) == nil)		return -1;	ctlr->mii->mir = fccmiimir;	ctlr->mii->miw = fccmiimiw;	ctlr->mii->ctlr = ctlr;	if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){		free(ctlr->mii);		ctlr->mii = nil;		return -1;	}	miiane(ctlr->mii, ~0, ~0, ~0);#ifdef DBG	print("oui=%X, phyno=%d, ", phy->oui, phy->phyno);	print("anar=%ux, ", phy->anar);	print("fc=%ux, ", phy->fc);	print("mscr=%ux, ", phy->mscr);	print("link=%ux, ", phy->link);	print("speed=%ux, ", phy->speed);	print("fd=%ux, ", phy->fd);	print("rfc=%ux, ", phy->rfc);	print("tfc=%ux\n", phy->tfc);#endif	/* Step 15, Enable ethernet: done at attach time */	return 0;}static intreset(Ether* ether){	uchar ea[Eaddrlen];	Ctlr *ctlr;	FCC *fcc;	Block *b;	int i;	if(m->cpuhz < 24000000){		print("%s ether: system speed must be >= 24MHz for ether use\n", ether->type);		return -1;	}	if(ether->port > 3){		print("%s ether: no FCC port %ld\n", ether->type, ether->port);		return -1;	}	ether->irq = fccirq[ether->port];	ether->tbdf = BusPPC;	fcc = imm->fcc + ether->port;	ctlr = malloc(sizeof(*ctlr));	ether->ctlr = ctlr;	memset(ctlr, 0, sizeof(*ctlr));	ctlr->fcc = fcc;	ctlr->port = ether->port;	ctlr->fccid = fccid[ether->port];	/* Ioringinit will allocate the buffer descriptors in normal memory	 * and NOT in Dual-Ported Ram, as prescribed by the MPC8260	 * PowerQUICC II manual (Section 28.6).  When they are allocated	 * in DPram and the Dcache is enabled, the processor will hang	 */	if(ioringinit(ctlr, Nrdre, Ntdre, 0) < 0)		panic("etherfcc init");	for(i = 0; i < Nrdre; i++){		b = iallocb(Bufsize);		b->rp = (uchar*)(((ulong)b->rp + CACHELINESZ-1) & ~(CACHELINESZ-1));		b->wp = b->rp;		ctlr->rcvbufs[i] = b;		ctlr->rdr[i].addr = PADDR(b->wp);	}	fccsetup(ctlr, fcc, ether->ea);	ether->mbps = 100;	/* TO DO: could be 10mbps */	ether->attach = attach;	ether->transmit = transmit;	ether->interrupt = interrupt;	ether->ifstat = ifstat;	ether->arg = ether;	ether->promiscuous = promiscuous;	ether->multicast = multicast;	/*	 * Until we know where to find it, insist that the plan9.ini	 * entry holds the Ethernet address.	 */	memset(ea, 0, Eaddrlen);	if(memcmp(ea, ether->ea, Eaddrlen) == 0){		print("no ether address");		return -1;	}	return 0;}voidetherfcclink(void){	addethercard("fcc", reset);}static voidnanodelay(void){	static int count;	int i;	for(i = 0; i < 500; i++)		count++;	return;}staticvoid miiwriteloop(Ctlr *ctlr, Port *port, int cnt, ulong cmd){	int i;	for(i = 0; i < cnt; i++){		port->pdat &= ~ctlr->pmdck;		if(cmd & BIT(i))			port->pdat |= ctlr->pmdio;		else			port->pdat &= ~ctlr->pmdio;		nanodelay();		port->pdat |= ctlr->pmdck;		nanodelay();	}}static intfccmiimiw(Mii *mii, int pa, int ra, int data){	int x;	Port *port;	ulong cmd;	Ctlr *ctlr;	/*	 * MII Management Interface Write.	 */	ctlr = mii->ctlr;	port = imm->port + 3;	cmd = MDIwrite | (pa<<(5+2+16))| (ra<<(2+16)) | (data & 0xffff);	x = splhi();	port->pdir |= (ctlr->pmdio|ctlr->pmdck);	nanodelay();	miiwriteloop(ctlr, port, 32, ~0);	miiwriteloop(ctlr, port, 32, cmd);	port->pdir |= (ctlr->pmdio|ctlr->pmdck);	nanodelay();	miiwriteloop(ctlr, port, 32, ~0);	splx(x);	return 1;}static intfccmiimir(Mii *mii, int pa, int ra){	int data, i, x;	Port *port;	ulong cmd;	Ctlr *ctlr;	ctlr = mii->ctlr;	port = imm->port + 3;	cmd = MDIread | pa<<(5+2+16) | ra<<(2+16);	x = splhi();	port->pdir |= (ctlr->pmdio|ctlr->pmdck);	nanodelay();	miiwriteloop(ctlr, port, 32, ~0);	/* Clock out the first 14 MS bits of the command */	miiwriteloop(ctlr, port, 14, cmd);	/* Turn-around */	port->pdat &= ~ctlr->pmdck;	port->pdir &= ~ctlr->pmdio;	nanodelay();	/* For read, clock in 18 bits, use 16 */	data = 0;	for(i=0; i<18; i++){		data <<= 1;		if(port->pdat & ctlr->pmdio)			data |= 1;		port->pdat |= ctlr->pmdck;		nanodelay();		port->pdat &= ~ctlr->pmdck;		nanodelay();	}	port->pdir |= (ctlr->pmdio|ctlr->pmdck);	nanodelay();	miiwriteloop(ctlr, port, 32, ~0);	splx(x);	return data & 0xffff;}static voidfccltimer(Ureg*, Timer *t){	Ether *ether;	Ctlr *ctlr;	MiiPhy *phy;	ulong gfmr;	ether = t->ta;	ctlr = ether->ctlr;	if(ctlr->mii == nil || ctlr->mii->curphy == nil)		return;	phy = ctlr->mii->curphy;	if(miistatus(ctlr->mii) < 0){		print("miistatus failed\n");		return;	}	if(phy->link == 0){		print("link lost\n");		return;	}	ether->mbps = phy->speed;	if(phy->fd != ctlr->duplex)		print("set duplex\n");	ilock(ctlr);	gfmr = ctlr->fcc->gfmr;	if(phy->fd != ctlr->duplex){		ctlr->fcc->gfmr &= ~(ENR|ENT);		if(phy->fd)			ctlr->fcc->fpsmr |= FDE | LPB;		/* full duplex operation */		else			ctlr->fcc->fpsmr &= ~(FDE | LPB);	/* half duplex operation */		ctlr->duplex = phy->fd;	}	ctlr->fcc->gfmr = gfmr;	iunlock(ctlr);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -