Beispiel #1
0
static void
rtl8139halt(Ctlr* ctlr)
{
	csr8w(ctlr, Cr, 0);
	csr16w(ctlr, Imr, 0);
	csr16w(ctlr, Isr, ~0);
}
Beispiel #2
0
static void
rtl8139init(Ether* edev)
{
	int i;
	uint32_t r;
	Ctlr *ctlr;
	uint8_t *alloc;

	ctlr = edev->ctlr;
	ilock(&ctlr->ilock);

	rtl8139halt(ctlr);

	/*
	 * MAC Address.
	 */
	r = (edev->ea[3]<<24)|(edev->ea[2]<<16)|(edev->ea[1]<<8)|edev->ea[0];
	csr32w(ctlr, Idr0, r);
	r = (edev->ea[5]<<8)|edev->ea[4];
	csr32w(ctlr, Idr0+4, r);

	/*
	 * Receiver
	 */
	alloc = (uint8_t*)ROUNDUP((uint32_t)ctlr->alloc, 32);
	ctlr->rbstart = alloc;
	alloc += ctlr->rblen+16;
	memset(ctlr->rbstart, 0, ctlr->rblen+16);
	csr32w(ctlr, Rbstart, PADDR(ctlr->rbstart));
	ctlr->rcr = Rxfth256|Rblen|Mrxdmaunlimited|Ab|Apm;

	/*
	 * Transmitter.
	 */
	for(i = 0; i < Ntd; i++){
		ctlr->td[i].tsd = Tsd0+i*4;
		ctlr->td[i].tsad = Tsad0+i*4;
		ctlr->td[i].data = alloc;
		alloc += Tdbsz;
	}
	ctlr->ntd = ctlr->tdh = ctlr->tdi = 0;
	ctlr->etxth = 128/32;

	/*
	 * Interrupts.
	 */
	csr32w(ctlr, TimerInt, 0);
	csr16w(ctlr, Imr, Serr|Timer|Fovw|PunLc|Rxovw|Ter|Tok|Rer|Rok);
	csr32w(ctlr, Mpc, 0);

	/*
	 * Enable receiver/transmitter.
	 * Need to enable before writing the Rcr or it won't take.
	 */
	csr8w(ctlr, Cr, Te|Re);
	csr32w(ctlr, Tcr, Mtxdma2048);
	csr32w(ctlr, Rcr, ctlr->rcr);

	iunlock(&ctlr->ilock);
}
Beispiel #3
0
static void
vt6102lproc(void* arg)
{
	Ctlr *ctlr;
	Ether *edev;
	MiiPhy *phy;

	edev = arg;
	ctlr = edev->ctlr;
	while(waserror())
		;
	for(;;){
		if(ctlr->mii == nil || ctlr->mii->curphy == nil)
			break;
		if(miistatus(ctlr->mii) < 0)
			goto enable;

		phy = ctlr->mii->curphy;
		ilock(&ctlr->clock);
		if(phy->fd)
			ctlr->cr |= Fdx;
		else
			ctlr->cr &= ~Fdx;
		csr16w(ctlr, Cr, ctlr->cr);
		iunlock(&ctlr->clock);
enable:
		ctlr->lwakeup = 0;
		vt6102imr(ctlr, Srci);

		ctlr->lsleep++;
		sleep(&ctlr->lrendez, vt6102wakeup, &ctlr->lwakeup);

	}
	pexit("vt6102lproc: done", 1);
}
Beispiel #4
0
static void
vt6102imr(Ctlr* ctlr, int imr)
{
	ilock(&ctlr->clock);
	ctlr->imr |= imr;
	csr16w(ctlr, Imr, ctlr->imr);
	iunlock(&ctlr->clock);
}
Beispiel #5
0
static void
vt6102transmit(Ether* edev)
{
	Block *bp;
	Ctlr *ctlr;
	Ds *ds, *next;
	int control, i, o, prefix, size, tdused, timeo;

	ctlr = edev->ctlr;

	ilock(&ctlr->tlock);

	/*
	 * Free any completed packets
	 */
	ds = ctlr->tdh;
	for(tdused = ctlr->tdused; tdused > 0; tdused--){
		/*
		 * For some errors the chip will turn the Tx engine
		 * off. Wait for that to happen.
		 * Could reset and re-init the chip here if it doesn't
		 * play fair.
		 * To do: adjust Tx FIFO threshold on underflow.
		 */
		if(ds->status & (Abt|Tbuff|Udf)){
			for(timeo = 0; timeo < 1000; timeo++){
				if(!(csr16r(ctlr, Cr) & Txon))
					break;
				microdelay(1);
			}
			ds->status = Own;
			csr32w(ctlr, Txdaddr, PCIWADDR(ds));
		}

		if(ds->status & Own)
			break;
		ds->addr = 0;
		ds->branch = 0;

		if(ds->bp != nil){
			freeb(ds->bp);
			ds->bp = nil;
		}
		for(i = 0; i < Ntxstats-1; i++){
			if(ds->status & (1<<i))
				ctlr->txstats[i]++;
		}
		ctlr->txstats[i] += (ds->status & NcrMASK)>>NcrSHIFT;

		ds = ds->next;
	}
	ctlr->tdh = ds;

	/*
	 * Try to fill the ring back up.
	 */
	ds = ctlr->tdt;
	while(tdused < ctlr->ntd-2){
		if((bp = qget(edev->oq)) == nil)
			break;
		tdused++;

		size = BLEN(bp);
		prefix = 0;

		if(o = (((int)bp->rp) & 0x03)){
			prefix = Txcopy-o;
			if(prefix > size)
				prefix = size;
			memmove(ds->bounce, bp->rp, prefix);
			ds->addr = PCIWADDR(ds->bounce);
			bp->rp += prefix;
			size -= prefix;
		}

		next = ds->next;
		ds->branch = PCIWADDR(ds->next);

		if(size){
			if(prefix){
				next->bp = bp;
				next->addr = PCIWADDR(bp->rp);
				next->branch = PCIWADDR(next->next);
				next->control = Edp|Chain|((size<<TbsSHIFT) & TbsMASK);

				control = Stp|Chain|((prefix<<TbsSHIFT) & TbsMASK);

				next = next->next;
				tdused++;
				ctlr->tsplit++;
			}
			else{
				ds->bp = bp;
				ds->addr = PCIWADDR(bp->rp);
				control = Edp|Stp|((size<<TbsSHIFT) & TbsMASK);
				ctlr->taligned++;
			}
		}
		else{
			freeb(bp);
			control = Edp|Stp|((prefix<<TbsSHIFT) & TbsMASK);
			ctlr->tcopied++;
		}

		ds->control = control;
		if(tdused >= ctlr->ntd-2){
			ds->control |= Ic;
			ctlr->txdw++;
		}
		coherence();
		ds->status = Own;

		ds = next;
	}
	ctlr->tdt = ds;
	ctlr->tdused = tdused;
	if(ctlr->tdused)
		csr16w(ctlr, Cr, Tdmd|ctlr->cr);

	iunlock(&ctlr->tlock);
}
Beispiel #6
0
static void
vt6102attach(Ether* edev)
{
	int dsz, i;
	Ctlr *ctlr;
	Ds *ds, *prev;
	uchar *alloc, *bounce;
	char name[KNAMELEN];

	ctlr = edev->ctlr;
	qlock(&ctlr->alock);
	if(ctlr->alloc != nil){
		qunlock(&ctlr->alock);
		return;
	}

	/*
	 * Descriptor and bounce-buffer space.
	 * Must all be aligned on a 4-byte boundary,
	 * but try to align on cache-lines.
	 */
	ctlr->nrd = Nrd;
	ctlr->ntd = Ntd;
	dsz = ROUNDUP(sizeof(Ds), ctlr->cls);
	alloc = mallocalign((ctlr->nrd+ctlr->ntd)*dsz + ctlr->ntd*Txcopy, dsz, 0, 0);
	if(alloc == nil){
		qunlock(&ctlr->alock);
		error(Enomem);
	}
	ctlr->alloc = alloc;

	ctlr->rd = (Ds*)alloc;

	if(waserror()){
		ds = ctlr->rd;
		for(i = 0; i < ctlr->nrd; i++){
			if(ds->bp != nil){
				freeb(ds->bp);
				ds->bp = nil;
			}
			if((ds = ds->next) == nil)
				break;
		}
		free(ctlr->alloc);
		ctlr->alloc = nil;
		qunlock(&ctlr->alock);
		nexterror();
	}

	prev = ctlr->rd + ctlr->nrd-1;
	for(i = 0; i < ctlr->nrd; i++){
		ds = (Ds*)alloc;
		alloc += dsz;

		ds->control = Rdbsz;
		ds->branch = PCIWADDR(alloc);

		ds->bp = iallocb(Rdbsz+3);
		if(ds->bp == nil)
			error("vt6102: can't allocate receive ring\n");
		ds->bp->rp = (uchar*)ROUNDUP((ulong)ds->bp->rp, 4);
		ds->addr = PCIWADDR(ds->bp->rp);

		ds->next = (Ds*)alloc;
		ds->prev = prev;
		prev = ds;

		ds->status = Own;
	}
	prev->branch = 0;
	prev->next = ctlr->rd;
	prev->status = 0;
	ctlr->rdh = ctlr->rd;

	ctlr->td = (Ds*)alloc;
	prev = ctlr->td + ctlr->ntd-1;
	bounce = alloc + ctlr->ntd*dsz;
	for(i = 0; i < ctlr->ntd; i++){
		ds = (Ds*)alloc;
		alloc += dsz;

		ds->bounce = bounce;
		bounce += Txcopy;
		ds->next = (Ds*)alloc;
		ds->prev = prev;
		prev = ds;
	}
	prev->next = ctlr->td;
	ctlr->tdh = ctlr->tdt = ctlr->td;
	ctlr->tdused = 0;

	ctlr->cr = Dpoll|Rdmd|Txon|Rxon|Strt;
	/*Srci|Abti|Norbf|Pktrace|Ovfi|Udfi|Be|Ru|Tu|Txe|Rxe|Ptx|Prx*/
	ctlr->imr = Abti|Norbf|Pktrace|Ovfi|Udfi|Be|Ru|Tu|Txe|Rxe|Ptx|Prx;

	ilock(&ctlr->clock);
	csr32w(ctlr, Rxdaddr, PCIWADDR(ctlr->rd));
	csr32w(ctlr, Txdaddr, PCIWADDR(ctlr->td));
	csr16w(ctlr, Isr, ~0);
	csr16w(ctlr, Imr, ctlr->imr);
	csr16w(ctlr, Cr, ctlr->cr);
	iunlock(&ctlr->clock);

	snprint(name, KNAMELEN, "#l%dlproc", edev->ctlrno);
	kproc(name, vt6102lproc, edev);

	qunlock(&ctlr->alock);
	poperror();
}