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

📄 ether83815.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
		if(status & Txurn){			ctlr->txurn++;			ilock(&ctlr->lock);			/* change threshold */			iunlock(&ctlr->lock);			status &= ~(Txurn);		}		ilock(&ctlr->tlock);		while(ctlr->ntq){			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			}			freeb(des->bp);			des->bp = nil;			des->cmdsts = 0;			ctlr->ntq--;			ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdr);		}		txstart(ether);		iunlock(&ctlr->tlock);		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 suitable aligned descriptors	 * for the transmit and receive rings;	 * initialise the receive ring;	 * initialise the transmit ring;	 * unmask interrupts and start the transmit side.	 */	des = xspanalloc((ctlr->nrdr+ctlr->ntdr)*sizeof(Des), 32, 0);	if(des == nil) {		print("ns83815: ctlrinit: iallocb of descs. failed\n");		return;	}	ctlr->tdr = des;	ctlr->rdr = des+ctlr->ntdr;	last = nil;	for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){		des->bp = iallocb(Rbsz);		if(des->bp == nil)			error(Enomem);		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));	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);	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);err:	;}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, v;	eeidle(ctlr);	eeclk(ctlr, 0);	eeclk(ctlr, Eeclk);	d = 0x180 | a;	for(i=0x400; i; i>>=1){		v = (d & i) ? Eedi : 0;		eeclk(ctlr, v);		eeclk(ctlr, Eeclk|v);	}	eeclk(ctlr, 0);	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 voidresetctlr(Ctlr *ctlr){	int i;	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);	}}static voidshutdown(Ether* ether){	Ctlr *ctlr = ether->ctlr;print("ether83815 shutting down\n");	csr32w(ctlr, Rcr, Rxd|Txd);	/* disable transceiver */	resetctlr(ctlr);}static voidsoftreset(Ctlr* ctlr, int resetphys){	int i, w;	/*	 * Soft-reset the controller	 */	resetctlr(ctlr);	csr32w(ctlr, Rccsr, Pmests);	csr32w(ctlr, Rccsr, 0);	csr32w(ctlr, Rcfg, csr32r(ctlr, Rcfg) | Pint_acen);	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);		for(i=0;; i++){			if(i > 6000){				print("ns83815: 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));}static intmedia(Ether* ether){	Ctlr* ctlr;	ulong cfg;	ctlr = ether->ctlr;	cfg = csr32r(ctlr, Rcfg);	ctlr->fd = (cfg & Fdup) != 0;	if(cfg & Speed100)		return 100;	if((cfg & Lnksts) == 0)		return 100;	/* no link: use 100 to ensure larger queues */	return 10;}static char* mediatable[9] = {	"10BASE-T",				/* TP */	"10BASE-2",				/* BNC */	"10BASE-5",				/* AUI */	"100BASE-TX",	"10BASE-TFD",	"100BASE-TXFD",	"100BASE-T4",	"100BASE-FX",	"100BASE-FXFD",};static intis630(ulong id, Pcidev *p){	if(id == SiS900)		switch (p->rid) {		case SiSrev630s:		case SiSrev630e:	  	case SiSrev630ea1:			return 1;		}	return 0;}enum {	MagicReg = 0x48,	MagicRegSz = 1,	Magicrden = 0x40,	/* read enable, apparently */	Paddr=		0x70,	/* address port */	Pdata=		0x71,	/* data port */	Pcinetctlr = 2,};/* rcmos() originally from LANL's SiS 900 driver's rcmos() */static intsisrdcmos(Ctlr *ctlr){	int i;	unsigned reg;	ulong port;	Pcidev *p;	debug("ns83815: SiS 630 rev. %ux reading mac address from cmos\n", ctlr->pcidev->rid);	p = pcimatch(nil, SiS, SiS630bridge);	if(p == nil) {		print("ns83815: no SiS 630 rev. %ux bridge for mac addr\n",			ctlr->pcidev->rid);		return 0;	}	port = p->mem[0].bar & ~0x01;	debug("ns83815: SiS 630 rev. %ux reading mac addr from cmos via bridge at port 0x%lux\n", ctlr->pcidev->rid, port);	reg = pcicfgr8(p, MagicReg);	pcicfgw8(p, MagicReg, reg|Magicrden);	for (i = 0; i < Eaddrlen; i++) {		outb(port+Paddr, SiS630eenodeaddr + i);		ctlr->sromea[i] = inb(port+Pdata);	}	pcicfgw8(p, MagicReg, reg & ~Magicrden);	return 1;}/* * If this is a SiS 630E chipset with an embedded SiS 900 controller, * we have to read the MAC address from the APC CMOS RAM. - sez freebsd. * However, CMOS *is* NVRAM normally.  See devrtc.c:440, memory.c:88. */static voidsissrom(Ctlr *ctlr){	union {		uchar	eaddr[Eaddrlen];		ushort	alignment;	} ee;	int i, off = SiSeenodeaddr, cnt = sizeof ee.eaddr / sizeof(short);	ushort *shp = (ushort *)ee.eaddr;	if(!is630(ctlr->id, ctlr->pcidev) || !sisrdcmos(ctlr)) {		for (i = 0; i < cnt; i++)			*shp++ = eegetw(ctlr, off++);		memmove(ctlr->sromea, ee.eaddr, sizeof ctlr->sromea);	}}static voidnssrom(Ctlr* ctlr){	int i, j;	for(i = 0; i < nelem(ctlr->srom); i++)		ctlr->srom[i] = eegetw(ctlr, i);	/*	 * the MAC address is reversed, straddling word boundaries	 */	j = Nseenodeaddr*16 + 15;	for(i=0; i<48; i++){		ctlr->sromea[i>>3] |= ((ctlr->srom[j>>4] >> (15-(j&0xF))) & 1) << (i&7);		j++;	}}static voidsrom(Ctlr* ctlr){	memset(ctlr->sromea, 0, sizeof(ctlr->sromea));	switch (ctlr->id) {	case SiS900:	case SiS7016:		sissrom(ctlr);		break;	case Nat83815:		nssrom(ctlr);		break;	default:		print("ns83815: srom: unknown id 0x%ux\n", ctlr->id);		break;	}}static voidscanpci83815(void){	Ctlr *ctlr;	Pcidev *p;	ulong id;	p = nil;	while(p = pcimatch(p, 0, 0)){		/* ccru is a short in the FS kernel, thus the cast to uchar */		if (p->ccrb != Pcinetctlr || (uchar)p->ccru != 0)			continue;		/* not a nic */		id = (p->did<<16)|p->vid;		switch(id){		default:			continue;		case Nat83815:		case SiS900:			break;		}		/*		 * bar[0] is the I/O port register address and		 * bar[1] is the memory-mapped register address.		 */		ctlr = mallocz(sizeof(Ctlr), 1);		ctlr->port = p->mem[0].bar & ~0x01;		ctlr->pcidev = p;		ctlr->id = id;		if(ioalloc(ctlr->port, p->mem[0].size, 0, "ns83815") < 0){			print("ns83815: port 0x%uX in use\n", ctlr->port);			free(ctlr);			continue;		}		softreset(ctlr, 0);		srom(ctlr);		if(ctlrhead != nil)			ctlrtail->next = ctlr;		else			ctlrhead = ctlr;		ctlrtail = ctlr;	}}/* multicast already on, don't need to do anything */static voidmulticast(void*, uchar*, int){}intdp83815reset(Ether* ether){	Ctlr *ctlr;	int i, x;	ulong ctladdr;	uchar ea[Eaddrlen];	static int scandone;	if(scandone == 0){		scanpci83815();		scandone = 1;	}	/*	 * Any adapter matches if no ether->port is supplied,	 * otherwise the ports must match.	 */	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){		if(ctlr->active)			continue;		if(ether->port == 0 || ether->port == ctlr->port){			ctlr->active = 1;			break;		}	}	if(ctlr == nil)		return -1;	ether->ctlr = ctlr;	ether->port = ctlr->port;	ether->irq = ctlr->pcidev->intl;	ether->tbdf = ctlr->pcidev->tbdf;	/*	 * Check if the adapter's station address is to be overridden.	 * If not, read it from the EEPROM and set in ether->ea prior to	 * loading the station address in the hardware.	 */	memset(ea, 0, Eaddrlen);	if(memcmp(ea, ether->ea, Eaddrlen) == 0)		memmove(ether->ea, ctlr->sromea, Eaddrlen);	for(i=0; i<Eaddrlen; i+=2){		x = ether->ea[i] | (ether->ea[i+1]<<8);		ctladdr = (ctlr->id == Nat83815? i: i<<15);		csr32w(ctlr, Rrfcr, ctladdr);		csr32w(ctlr, Rrfdr, x);	}	csr32w(ctlr, Rrfcr, Rfen|Apm|Aab|Aam);	ether->mbps = media(ether);	/*	 * Look for a medium override in case there's no autonegotiation	 * the autonegotiation fails.	 */	for(i = 0; i < ether->nopt; i++){		if(cistrcmp(ether->opt[i], "FD") == 0){			ctlr->fd = 1;			continue;		}		for(x = 0; x < nelem(mediatable); x++){			debug("compare <%s> <%s>\n", mediatable[x],				ether->opt[i]);			if(cistrcmp(mediatable[x], ether->opt[i]) == 0){				if(x != 4 && x >= 3)					ether->mbps = 100;				else					ether->mbps = 10;				switch(x){				default:					ctlr->fd = 0;					break;				case 0x04:		/* 10BASE-TFD */				case 0x05:		/* 100BASE-TXFD */				case 0x08:		/* 100BASE-FXFD */					ctlr->fd = 1;					break;				}				break;			}		}	}	/*	 * Initialise descriptor rings, ethernet address.	 */	ctlr->nrdr = Nrde;	ctlr->ntdr = Ntde;	pcisetbme(ctlr->pcidev);	ctlrinit(ether);	/*	 * Linkage to the generic ethernet driver.	 */	ether->attach = attach;	ether->transmit = transmit;	ether->interrupt = interrupt;#ifndef FS	ether->ifstat = ifstat;	ether->arg = ether;	ether->promiscuous = promiscuous;	ether->multicast = multicast;	ether->shutdown = shutdown;#endif	debug("ns83815: dp83815reset: done\n");	return 0;}#ifndef FSvoidether83815link(void){	addethercard("83815",  dp83815reset);}#endif

⌨️ 快捷键说明

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