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

📄 ether83815.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
			status &= ~(Txurn);		}		ilock(&ctlr->tlock);		while(ctlr->ntq){			des = &ctlr->tdr[ctlr->tdri];			cmdsts = des->cmdsts;			if(cmdsts & Own)				break;			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 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));	last = nil;	for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){		des->bp = allocb(Rbsz);		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);	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);}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;	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);	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 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;	p = nil;	while(p = pcimatch(p, 0, 0)){		if(p->ccrb != 0x02 || p->ccru != 0)			continue;		switch((p->did<<16)|p->vid){		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 = malloc(sizeof(Ctlr));		ctlr->port = p->mem[0].bar & ~0x01;		ctlr->pcidev = p;		ctlr->id = (p->did<<16)|p->vid;		softreset(ctlr, 0);		srom(ctlr);		if(ctlrhead != nil)			ctlrtail->next = ctlr;		else			ctlrhead = ctlr;		ctlrtail = ctlr;	}}intether83815reset(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);	/*	 * 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){				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;	ether->detach = detach;	return 0;}

⌨️ 快捷键说明

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