Beispiel #1
0
static int
w_write(Ctlr* ctlr, int type, int off, void* buf, ulong len)
{
    int tries;

    for (tries=0; tries < WTmOut; tries++) {
        if(w_seek(ctlr, type, off, 0)) {
            DEBUG("wavelan: w_write: seek failed\n");
            return 0;
        }

        csr_outss(ctlr, WR_Data0, buf, len/2);

        csr_outs(ctlr, WR_Data0, 0xdead);
        csr_outs(ctlr, WR_Data0, 0xbeef);
        if(w_seek(ctlr, type, off + len, 0)) {
            DEBUG("wavelan: write seek failed\n");
            return 0;
        }
        if(csr_ins(ctlr, WR_Data0) == 0xdead)
            if(csr_ins(ctlr, WR_Data0) == 0xbeef)
                return len;
        DEBUG("wavelan: Hermes bug byte.\n");
        return 0;
    }
    DEBUG("wavelan: tx timeout\n");
    return 0;
}
Beispiel #2
0
int
w_cmd(Ctlr *ctlr, ushort cmd, ushort arg)
{
	int i, rc;

	for(i=0; i<WTmOut; i++)
		if((csr_ins(ctlr, WR_Cmd)&WCmdBusy) == 0)
			break;
	if(i==WTmOut){
		print("#l%d: issuing cmd %.4ux: %.4ux\n", ctlr->ctlrno, cmd, csr_ins(ctlr, WR_Cmd));
		return -1;
	}

	csr_outs(ctlr, WR_Parm0, arg);
	csr_outs(ctlr, WR_Cmd, cmd);

	for(i=0; i<WTmOut; i++)
		if(csr_ins(ctlr, WR_EvSts)&WCmdEv)
			break;
	if(i==WTmOut){
		/*
		 * WCmdIni can take a really long time.
		 */
		enum { IniTmOut = 2000 };
		for(i=0; i<IniTmOut; i++){
			if(csr_ins(ctlr, WR_EvSts)&WCmdEv)
				break;
			microdelay(100);
		}
		if(i < IniTmOut)
			if(0) print("#l%d: long cmd %.4ux %d\n", ctlr->ctlrno, cmd, i);
		if(i == IniTmOut){
			print("#l%d: execing cmd %.4ux: %.4ux\n", ctlr->ctlrno, cmd, csr_ins(ctlr, WR_EvSts));
			return -1;
		}
	}
	rc = csr_ins(ctlr, WR_Sts);
	csr_ack(ctlr, WCmdEv);

	if((rc&WCmdMsk) != (cmd&WCmdMsk)){
		print("#l%d: cmd %.4ux: status %.4ux\n", ctlr->ctlrno, cmd, rc);
		return -1;
	}
	if(rc&WResSts){
		/*
		 * Don't print; this happens on every WCmdAccWr for some reason.
		 */
		if(0) print("#l%d: cmd %.4ux: status %.4ux\n", ctlr->ctlrno, cmd, rc);
		return -1;
	}
	return 0;
}
Beispiel #3
0
static int
w_seek(Ctlr* ctlr, ushort id, ushort offset, int chan)
{
	int i, rc;
	static ushort sel[] = { WR_Sel0, WR_Sel1 };
	static ushort off[] = { WR_Off0, WR_Off1 };

	if(chan != 0 && chan != 1)
		panic("wavelan: bad chan");
	csr_outs(ctlr, sel[chan], id);
	csr_outs(ctlr, off[chan], offset);
	for (i=0; i<WTmOut; i++){
		rc = csr_ins(ctlr, off[chan]);
		if((rc & (WBusyOff|WErrOff)) == 0)
			return 0;
	}
	return -1;
}
Beispiel #4
0
static void
w_intr(Ether *ether)
{
	int rc, txid;
	Ctlr* ctlr = (Ctlr*) ether->ctlr;

	if((ctlr->state & Power) == 0)
		return;

	if((ctlr->state & Attached) == 0){
		csr_ack(ctlr, 0xffff);
		csr_outs(ctlr, WR_IntEna, 0);
		return;
	}

	rc = csr_ins(ctlr, WR_EvSts);
	csr_ack(ctlr, ~WEvs);	// Not interested in them
	if(rc & WRXEv){
		w_rxdone(ether);
		csr_ack(ctlr, WRXEv);
	}
	if(rc & WTXEv){
		w_txdone(ctlr, rc);
		csr_ack(ctlr, WTXEv);
	}
	if(rc & WAllocEv){
		ctlr->nalloc++;
		txid = csr_ins(ctlr, WR_Alloc);
		csr_ack(ctlr, WAllocEv);
		if(txid == ctlr->txdid){
			if((rc & WTXEv) == 0)
				w_txdone(ctlr, rc);
		}
	}
	if(rc & WInfoEv){
		ctlr->ninfo++;
		w_info(ether, ctlr);
		csr_ack(ctlr, WInfoEv);
	}
	if(rc & WTxErrEv){
		w_txdone(ctlr, rc);
		csr_ack(ctlr, WTxErrEv);
	}
	if(rc & WIDropEv){
		ctlr->nidrop++;
		csr_ack(ctlr, WIDropEv);
	}
	w_txstart(ether);
}
Beispiel #5
0
static int
w_alloc(Ctlr* ctlr, int len)
{
	int rc;
	int i,j;

	if(w_cmd(ctlr, WCmdMalloc, len)==0)
		for (i = 0; i<WTmOut; i++)
			if(csr_ins(ctlr, WR_EvSts) & WAllocEv){
				csr_ack(ctlr, WAllocEv);
				rc=csr_ins(ctlr, WR_Alloc);
				if(w_seek(ctlr, rc, 0, 0))
					return -1;
				len = len/2;
				for (j=0; j<len; j++)
					csr_outs(ctlr, WR_Data0, 0);
				return rc;
			}
	return -1;
}
Beispiel #6
0
void
w_intdis(Ctlr* ctlr)
{
	csr_outs(ctlr, WR_IntEna, 0);
	csr_ack(ctlr, 0xffff);
}
Beispiel #7
0
static void
csr_ack(Ctlr *ctlr, int ev)
{
	csr_outs(ctlr, WR_EvAck, ev);
}
Beispiel #8
0
static void
w_intena(Ctlr* ctlr)
{
	csr_outs(ctlr, WR_IntEna, WEvs);
}