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

📄 ether83815.mii.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
static voidtransmit(Ether* ether){	Ctlr *ctlr;	ctlr = ether->ctlr;	ilock(&ctlr->tlock);	txstart(ether);	iunlock(&ctlr->tlock);}// TODO: finish this; set speed toostatic voidtxrxcfg(Ctlr *ctlr, int txdrth){	ulong rx, tx;	rx = csr32r(ctlr, Rrxcfg);	tx = csr32r(ctlr, Rtxcfg);	if(ctlr->fd){		rx |= Atx;		tx |= Csi | Hbi;	}else{		rx &= ~Atx;		tx &= ~(Csi | Hbi);	}	tx &= ~(Mxdma|Drth|Flth);	tx |= Mxdma64 | Flth128 | txdrth;	csr32w(ctlr, Rtxcfg, tx);	rx &= ~(Mxdma|Rdrth);	rx |= Mxdma64 | Rdrth64;	csr32w(ctlr, Rrxcfg, rx);}static voidinterrupt(Ureg*, void* arg){	Ctlr *ctlr;	Ether *ether;	int len, status, cmdsts, iter = 0;	Des *des;	Block *bp;	ether = arg;	ctlr = ether->ctlr;	while((status = csr32r(ctlr, Risr)) != 0){		if (iter++ >= 100)			print("ns83815: interrupt: >= 100 iterations\n");		status &= ~(Pme|Mib);		if(status & Hiberr){			if(status & Rxsovr)				ctlr->rxsover++;			if(status & Sserr)				ctlr->sserr++;			if(status & Dperr)				ctlr->dperr++;			if(status & Rmabt)				ctlr->rmabt++;			if(status & Rtabt)				ctlr->rtabt++;			status &= ~(Hiberr|Txrcmp|Rxrcmp|Rxsovr|Dperr|Sserr|Rmabt|Rtabt);		}		/*		 * Received packets.		 */		if(status & (Rxdesc|Rxok|Rxerr|Rxearly|Rxorn)){			des = &ctlr->rdr[ctlr->rdrx];			while((cmdsts = des->cmdsts) & Own){				if((cmdsts&Ok) == 0){					if(cmdsts & Rxa)						ctlr->rxa++;					if(cmdsts & Rxo)						ctlr->rxo++;					if(cmdsts & Long)						ctlr->rlong++;					if(cmdsts & Runt)						ctlr->runt++;					if(cmdsts & Ise)						ctlr->ise++;					if(cmdsts & Crce)						ctlr->crce++;					if(cmdsts & Fae)						ctlr->fae++;					if(cmdsts & Lbp)						ctlr->lbp++;					if(cmdsts & Col)						ctlr->col++;				}				else if(bp = iallocb(Rbsz)){					len = (cmdsts&Size)-4;					if (len <= 0) {						print(				"ns83815: interrupt: packet len %d <= 0\n",							len);						freeb(des->bp);	/* toss it */					} else {						SETWPCNT(des->bp, len);						ETHERIQ(ether, des->bp, 1);					}					/* replace just-queued/freed packet */					des->bp = bp;					des->addr = PADDR(bp->rp);//					debug(//		"ns83815: interrupt: packet into input q, new des->addr %lux\n",//						des->addr);					coherence();				} else {					print(		"ns83815: interrupt: iallocb for input buffer failed\n");					/*					 * prevent accidents & ignore this					 * packet.  it will be overwritten.					 */					des->bp->next = 0;				}				des->cmdsts = Rbsz;				coherence();				ctlr->rdrx = NEXT(ctlr->rdrx, ctlr->nrdr);				des = &ctlr->rdr[ctlr->rdrx];			}			status &= ~(Rxdesc|Rxok|Rxerr|Rxearly|Rxorn);		}		/*		 * Check the transmit side:		 *	check for Transmit Underflow and Adjust		 *	the threshold upwards;		 *	free any transmitted buffers and try to		 *	top-up the ring.		 */		if(status & Txurn){			ctlr->txurn++;			ilock(&ctlr->lock);			/* change threshold */			iunlock(&ctlr->lock);			status &= ~(Txurn);		}		ilock(&ctlr->tlock);		while(ctlr->ntq > 0){			des = &ctlr->tdr[ctlr->tdri];			cmdsts = des->cmdsts;			if(cmdsts & Own)				break;			if((cmdsts & Ok) == 0){				if(cmdsts & Txa)					ctlr->txa++;				if(cmdsts & Tfu)					ctlr->tfu++;				if(cmdsts & Td)					ctlr->td++;				if(cmdsts & Ed)					ctlr->ed++;				if(cmdsts & Owc)					ctlr->owc++;				if(cmdsts & Ec)					ctlr->ec++;#ifndef FS				ether->oerrs++;#endif			}//			debug("ns83815: interrupt: done output for des->addr %lux\n",//				des->addr);			if (des->bp == nil)				panic("83815 interrupt: nil des->bp");			freeb(des->bp);			des->bp = nil;			des->cmdsts = 0;			ctlr->ntq--;			ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdr);		}		txstart(ether);		iunlock(&ctlr->tlock);		if((status & Phy) && ctlr->mii != nil){			ctlr->mii->mir(ctlr->mii, 1, Bmsr);			print("phy: cfg %8.8lux bmsr %4.4ux\n",				csr32r(ctlr, Rcfg),				ctlr->mii->mir(ctlr->mii, 1, Bmsr));			/* TODO: set speed too; can't do it yet */			txrxcfg(ctlr, Drth512);	/* set duplicity */			status &= ~Phy;		}		status &= ~(Txurn|Txidle|Txerr|Txdesc|Txok);		/*		 * Anything left not catered for?		 */		if(status)			print("#l%d: status %8.8ux\n", ether->ctlrno, status);	}}static voidctlrinit(Ether* ether){	Ctlr *ctlr;	Des *des, *last;	ctlr = ether->ctlr;	/*	 * Allocate and initialise the receive ring;	 * allocate and initialise the transmit ring;	 * unmask interrupts and start the transmit side	 */	ctlr->rdr = malloc(ctlr->nrdr*sizeof(Des));	if(ctlr->rdr == nil) {		print("ns83815: ctlrinit: iallocb of rcv. descs. failed\n");		return;	}	last = nil;	for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){		des->bp = iallocb(Rbsz);		if (des->bp == nil) {			print("ns83815: ctlrinit: iallocb(%d) failed\n", Rbsz);			return;		}		des->cmdsts = Rbsz;		des->addr = PADDR(des->bp->rp);		if(last != nil)			last->next = PADDR(des);		last = des;	}	ctlr->rdr[ctlr->nrdr-1].next = PADDR(ctlr->rdr);	ctlr->rdrx = 0;	csr32w(ctlr, Rrxdp, PADDR(ctlr->rdr));	ctlr->tdr = xspanalloc(ctlr->ntdr*sizeof(Des), 8*sizeof(ulong), 0);	last = nil;	for(des = ctlr->tdr; des < &ctlr->tdr[ctlr->ntdr]; des++){		des->cmdsts = 0;		des->bp = nil;		des->addr = ~0;		if(last != nil)			last->next = PADDR(des);		last = des;	}	ctlr->tdr[ctlr->ntdr-1].next = PADDR(ctlr->tdr);	ctlr->tdrh = 0;	ctlr->tdri = 0;	csr32w(ctlr, Rtxdp, PADDR(ctlr->tdr));	txrxcfg(ctlr, Drth512);// TODO: finish this// MII	csr32w(ctlr, Rimr, Dperr|Sserr|Rmabt|Rtabt|Rxsovr|Hiberr|Txurn|Txerr|		Txdesc|Txok|Rxorn|Rxerr|Rxdesc|Rxok);	/* Phy|Pme|Mib */	csr32r(ctlr, Risr);	/* clear status */	csr32w(ctlr, Rier, Ie);	debug("ns83815: ctlrinit: set Ie, done\n");}/* * EEPROM */static voideeclk(Ctlr *ctlr, int clk){	csr32w(ctlr, Rmear, Eesel | clk);	microdelay(2);}static voideeidle(Ctlr *ctlr){	int i;	eeclk(ctlr, 0);	eeclk(ctlr, Eeclk);	for(i=0; i<25; i++){		eeclk(ctlr, 0);		eeclk(ctlr, Eeclk);	}	eeclk(ctlr, 0);	csr32w(ctlr, Rmear, 0);	microdelay(2);}static inteegetw(Ctlr *ctlr, int a){	int d, i, w;	eeidle(ctlr);	eeclk(ctlr, 0);	eeclk(ctlr, Eeclk);	d = 0x180 | a;			// read EEPROM at address `a'	for(i=0x400; i; i>>=1){		if(d & i)			csr32w(ctlr, Rmear, Eesel|Eedi);		else			csr32w(ctlr, Rmear, Eesel);		eeclk(ctlr, Eeclk);		eeclk(ctlr, 0);		microdelay(2);	}	w = 0;	for(i=0x8000; i; i >>= 1){		eeclk(ctlr, Eeclk);		if(csr32r(ctlr, Rmear) & Eedo)			w |= i;		microdelay(2);		eeclk(ctlr, 0);	}	eeidle(ctlr);	return w;}static voidsoftreset(Ctlr* ctlr, int resetphys){	int i, w;	/*	 * Soft-reset the controller	 */	csr32w(ctlr, Rcr, Rst);	for(i=0;; i++){		if(i > 100)			panic("ns83815: soft reset did not complete");		microdelay(250);		if((csr32r(ctlr, Rcr) & Rst) == 0)			break;		delay(1);	}	csr32w(ctlr, Rccsr, Pmests);	csr32w(ctlr, Rccsr, 0);	csr32w(ctlr, Rcfg, csr32r(ctlr, Rcfg) | Pint_acen);// MII// TODO: finish this	if(resetphys){		/*		 * Soft-reset the PHY		 */		csr32w(ctlr, Rbmcr, Reset);		for(i=0;; i++){			if(i > 100)				panic("ns83815: PHY soft reset time out");			if((csr32r(ctlr, Rbmcr) & Reset) == 0)				break;			delay(1);		}	}	/*	 * Initialisation values, in sequence (see 4.4 Recommended Registers Configuration)	 */	csr16w(ctlr, 0xCC, 0x0001);	/* PGSEL */	csr16w(ctlr, 0xE4, 0x189C);	/* PMCCSR */	csr16w(ctlr, 0xFC, 0x0000);	/* TSTDAT */	csr16w(ctlr, 0xF4, 0x5040);	/* DSPCFG */	csr16w(ctlr, 0xF8, 0x008C);	/* SDCFG */	/*	 * Auto negotiate	 */	w = csr16r(ctlr, Rbmsr);	/* clear latched bits */	debug("anar: %4.4ux\n", csr16r(ctlr, Ranar));	csr16w(ctlr, Rbmcr, Anena);	if(csr16r(ctlr, Ranar) == 0 || (csr32r(ctlr, Rcfg) & Aneg_dn) == 0){		csr16w(ctlr, Rbmcr, Anena|Anrestart);		/* TODO: this times out on the SiS900. why? */// TODO: finish this		for(i=0;; i++){			if(i > 6000){				print("ns83815: speed auto neg. timed out\n");				break;			}			if((w = csr16r(ctlr, Rbmsr)) & Ancomp)				break;			delay(1);		}		debug("%d ms\n", i);		w &= 0xFFFF;		debug("bmsr: %4.4ux\n", w);		USED(w);	}	debug("anar: %4.4ux\n", csr16r(ctlr, Ranar));	debug("anlpar: %4.4ux\n", csr16r(ctlr, Ranlpar));	debug("aner: %4.4ux\n", csr16r(ctlr, Raner));	debug("physts: %4.4ux\n", csr16r(ctlr, Rphysts));	debug("tbscr: %4.4ux\n", csr16r(ctlr, Rtbscr));}/* * MII/PHY */// TODO: finish thisstatic intmdior(Ctlr* ctlr, int n){	int data, i, mear, r;//	mear = csr32r(ctlr, Mear);//	r = ~(Mdc|Mddir) & mear;	data = 0;	for(i = n-1; i >= 0; i--){//		if(csr32r(ctlr, Mear) & Mdio)			data |= (1<<i);//		csr32w(ctlr, Mear, Mdc|r);//		csr32w(ctlr, Mear, r);	}//	csr32w(ctlr, Mear, mear);	return data;}// TODO: finish thisstatic voidmdiow(Ctlr* ctlr, int bits, int n){	int i, mear, r;//	mear = csr32r(ctlr, Mear);//	r = Mddir|(~Mdc & mear);	for(i = n-1; i >= 0; i--){//		if(bits & (1<<i))//			r |= Mdio;//		else//			r &= ~Mdio;//		csr32w(ctlr, Mear, r);//		csr32w(ctlr, Mear, Mdc|r);	}//	csr32w(ctlr, Mear, mear);}static intns83815miimir(Mii* mii, int pa, int ra){	int data;	Ctlr *ctlr;	ctlr = mii->ctlr;	/*	 * MII Management Interface Read.	 *	 * Preamble;	 * ST+OP+PA+RA;	 * LT + 16 data bits.	 */	mdiow(ctlr, 0xFFFFFFFF, 32);	mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);

⌨️ 快捷键说明

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