shithub: riscv

Download patch

ref: 78fc90ec86481dac7d9528a446fa4624631e5a26
parent: 8d271549cdc06d7c1cbc8496261be118e90f5e24
author: cinap_lenrek <[email protected]>
date: Tue Feb 12 09:28:22 EST 2013

etheriwl: support for WiFi Link 4965

--- a/sys/src/9/pc/etheriwl.c
+++ b/sys/src/9/pc/etheriwl.c
@@ -19,7 +19,6 @@
 #include "wifi.h"
 
 enum {
-
 	Ntxlog		= 8,
 	Ntx		= 1<<Ntxlog,
 	Nrxlog		= 8,
@@ -197,16 +196,18 @@
 enum {
 	SchedBase		= 0xa02c00,
 	SchedSramAddr		= SchedBase,
-	SchedDramAddr5000	= SchedBase+0x008,
+
 	SchedDramAddr4965	= SchedBase+0x010,
-	SchedTxFact5000		= SchedBase+0x010,
 	SchedTxFact4965		= SchedBase+0x01c,
 	SchedQueueRdptr4965	= SchedBase+0x064,	// +q*4
-	SchedQueueRdptr5000	= SchedBase+0x068,	// +q*4
 	SchedQChainSel4965	= SchedBase+0x0d0,
 	SchedIntrMask4965	= SchedBase+0x0e4,
-	SchedQChainSel5000	= SchedBase+0x0e8,
 	SchedQueueStatus4965	= SchedBase+0x104,	// +q*4
+
+	SchedDramAddr5000	= SchedBase+0x008,
+	SchedTxFact5000		= SchedBase+0x010,
+	SchedQueueRdptr5000	= SchedBase+0x068,	// +q*4
+	SchedQChainSel5000	= SchedBase+0x0e8,
 	SchedIntrMask5000	= SchedBase+0x108,
 	SchedQueueStatus5000	= SchedBase+0x10c,	// +q*4
 	SchedAggrSel5000	= SchedBase+0x248,
@@ -215,11 +216,9 @@
 enum {
 	SchedCtxOff4965		= 0x380,
 	SchedCtxLen4965		= 416,
-	SchedTransTblOff4965	= 0x500,
 
 	SchedCtxOff5000		= 0x600,
 	SchedCtxLen5000		= 512,
-	SchedTransTblOff5000	= 0x7e0,
 };
 
 enum {
@@ -253,8 +252,6 @@
 
 typedef struct Ctlr Ctlr;
 
-typedef struct Ctlrtype Ctlrtype;
-
 struct FWSect
 {
 	uchar	*data;
@@ -378,41 +375,18 @@
 	Type6005	= 11,
 };
 
-struct Ctlrtype
-{
-	char	*fwname;
+static char *fwname[16] = {
+	[Type4965] "iwn-4965",
+	[Type5300] "iwn-5000",
+	[Type5350] "iwn-5000",
+	[Type5150] "iwn-5150",
+	[Type5100] "iwn-5000",
+	[Type1000] "iwn-1000",
+	[Type6000] "iwn-6000",
+	[Type6050] "iwn-6050",
+	[Type6005] "iwn-6005",
 };
 
-static Ctlrtype ctlrtype[16] = {
-	[Type4965] {
-		.fwname = "iwn-4965",
-	},
-	[Type5300] {
-		.fwname = "iwn-5000",
-	},
-	[Type5350] {
-		.fwname = "iwn-5000",
-	},
-	[Type5150] {
-		.fwname = "iwn-5150",
-	},
-	[Type5100] {
-		.fwname = "iwn-5000",
-	},
-	[Type1000] {
-		.fwname = "iwn-1000",
-	},
-	[Type6000] {
-		.fwname = "iwn-6000",
-	},
-	[Type6050] {
-		.fwname = "iwn-6050",
-	},
-	[Type6005] {
-		.fwname = "iwn-6005",
-	},
-};
-
 #define csr32r(c, r)	(*((c)->nic+((r)/4)))
 #define csr32w(c, r, v)	(*((c)->nic+((r)/4)) = (v))
 
@@ -754,7 +728,7 @@
 			return "bad firmware signature";
 		p += 4;
 		strncpy(i->descr, (char*)p, 64);
-		i->descr[sizeof(i->descr)-1] = 0;
+		i->descr[64] = 0;
 		p += 64;
 		i->rev = get32(p); p += 4;
 		i->build = get32(p); p += 4;
@@ -776,7 +750,7 @@
 			default:s = &dummy;
 			}
 			p += 2;
-			if(get16(p) != alt)
+			if(get16(p) != 0 && get16(p) != alt)
 				s = &dummy;
 			p += 2;
 			s->size = get32(p); p += 4;
@@ -942,6 +916,7 @@
 			return err;
 		if((err = loadfirmware1(ctlr, 0x00800000, fw->main.data.data, fw->main.data.size)) != nil)
 			return err;
+		csr32w(ctlr, Reset, 0);
 		goto bootmain;
 	}
 
@@ -966,6 +941,12 @@
 	prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p) >> 4);
 	prphwrite(ctlr, BsmDramTextSize, fw->init.text.size);
 
+	nicunlock(ctlr);
+	if((err = niclock(ctlr)) != nil){
+		free(dma);
+		return err;
+	}
+
 	p = fw->boot.text.data;
 	n = fw->boot.text.size/4;
 	for(i=0; i<n; i++, p += 4)
@@ -1019,7 +1000,6 @@
 	nicunlock(ctlr);
 
 bootmain:
-	csr32w(ctlr, Reset, 0);
 	if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive){
 		free(dma);
 		return "main firmware boot failed";
@@ -1120,17 +1100,18 @@
 
 
 static void
-cmd(Ctlr *ctlr, uint code, uchar *data, int size)
+flushcmd(Ctlr *ctlr)
 {
-	qcmd(ctlr, 4, code, data, size, nil);
+	flushq(ctlr, 4);
 }
 
 static void
-flushcmd(Ctlr *ctlr)
+cmd(Ctlr *ctlr, uint code, uchar *data, int size)
 {
-	flushq(ctlr, 4);
+	qcmd(ctlr, 4, code, data, size, nil);
 }
 
+
 static void
 setled(Ctlr *ctlr, int which, int on, int off)
 {
@@ -1173,8 +1154,8 @@
 	}
 
 	ctlr->sched.base = prphread(ctlr, SchedSramAddr);
-	for(i=0; i < ctxlen/4; i++)
-		memwrite(ctlr, ctlr->sched.base + ctxoff + i*4, 0);
+	for(i=0; i < ctxlen; i += 4)
+		memwrite(ctlr, ctlr->sched.base + ctxoff + i, 0);
 
 	prphwrite(ctlr, dramaddr, PCIWADDR(ctlr->sched.s)>>10);
 
@@ -1185,7 +1166,7 @@
 		prphwrite(ctlr, SchedQChainSel5000, 0xfffef);
 		prphwrite(ctlr, SchedAggrSel5000, 0);
 
-		for(q=0; q<nelem(ctlr->tx); q++){
+		for(q=0; q<20; q++){
 			prphwrite(ctlr, SchedQueueRdptr5000 + q*4, 0);
 			csr32w(ctlr, HbusTargWptr, q << 8);
 
@@ -1217,25 +1198,26 @@
 
 	/* Mark TX rings (4 EDCA + cmd + 2 HCCA) as active. */
 	for(q=0; q<7; q++){
-		static uchar qid2fifo[] = { 3, 2, 1, 0, 7, 5, 6 };
-		if(ctlr->type != Type4965)
+		if(ctlr->type != Type4965){
+			static uchar qid2fifo[] = { 3, 2, 1, 0, 7, 5, 6 };
 			prphwrite(ctlr, SchedQueueStatus5000 + q*4, 0x00ff0018 | qid2fifo[q]);
-		else
-			prphwrite(ctlr, SchedQueueStatus4965 + q*4, 0x0007fc01 | qid2fifo[q]);
+		} else {
+			static uchar qid2fifo[] = { 3, 2, 1, 0, 4, 5, 6 };
+			prphwrite(ctlr, SchedQueueStatus4965 + q*4, 0x0007fc01 | qid2fifo[q]<<1);
+		}
 	}
 	nicunlock(ctlr);
 
-	if(ctlr->type != Type5150){
-		memset(c, 0, sizeof(c));
-		c[0] = 15;	/* code */
-		c[1] = 0;	/* grup */
-		c[2] = 1;	/* ngroup */
-		c[3] = 1;	/* isvalid */
-		put16(c+4, ctlr->eeprom.crystal);
-		cmd(ctlr, 176, c, 8);
-	}
-
 	if(ctlr->type != Type4965){
+		if(ctlr->type != Type5150){
+			memset(c, 0, sizeof(c));
+			c[0] = 15;	/* code */
+			c[1] = 0;	/* grup */
+			c[2] = 1;	/* ngroup */
+			c[3] = 1;	/* isvalid */
+			put16(c+4, ctlr->eeprom.crystal);
+			cmd(ctlr, 176, c, 8);
+		}
 		put32(c, ctlr->rfcfg.txantmask & 7);
 		cmd(ctlr, 152, c, 4);
 	}
@@ -1266,15 +1248,15 @@
 		p += 8;		/* tcs */
 		p += 8;		/* rxmic */
 		p += 8;		/* txmic */
-		p += 4;		/* htflags */
-		p += 4;		/* mask */
-		p += 2;		/* disable tid */
-		p += 2;		/* reserved */
-		p++;		/* add ba tid */
-		p++;		/* del ba tid */
-		p += 2;		/* add ba ssn */
-		p += 4;		/* reserved */
 	}
+	p += 4;		/* htflags */
+	p += 4;		/* mask */
+	p += 2;		/* disable tid */
+	p += 2;		/* reserved */
+	p++;		/* add ba tid */
+	p++;		/* del ba tid */
+	p += 2;		/* add ba ssn */
+	p += 4;		/* reserved */
 	cmd(ctlr, 24, c, p - c);
 }
 
@@ -1344,6 +1326,7 @@
 		p += 2;				/* reserved */
 	}
 	cmd(ctlr, 16, c, p - c);
+
 	if(ctlr->bcastnodeid == -1){
 		ctlr->bcastnodeid = (ctlr->type != Type4965) ? 15 : 31;
 		addnode(ctlr, ctlr->bcastnodeid, edev->bcast);
@@ -1617,10 +1600,10 @@
 			ctlr->wifi = wifiattach(edev, transmit);
 
 		if(ctlr->fw == nil){
-			fw = readfirmware(ctlrtype[ctlr->type].fwname);
+			fw = readfirmware(fwname[ctlr->type]);
 			print("#l%d: firmware: %s, rev %ux, build %ud, size %ux+%ux+%ux+%ux+%ux\n",
 				edev->ctlrno,
-				ctlrtype[ctlr->type].fwname,
+				fwname[ctlr->type],
 				fw->rev, fw->build,
 				fw->main.text.size, fw->main.data.size,
 				fw->init.text.size, fw->init.data.size,
@@ -1699,18 +1682,20 @@
 		if((err = niclock(ctlr)) != nil)
 			error(err);
 
-		prphwrite(ctlr, SchedTxFact5000, 0);
+		if(ctlr->type != Type4965)
+			prphwrite(ctlr, SchedTxFact5000, 0);
+		else
+			prphwrite(ctlr, SchedTxFact4965, 0);
 
 		csr32w(ctlr, FhKwAddr, PCIWADDR(ctlr->kwpage) >> 4);
 
-		for(q=0; q<nelem(ctlr->tx); q++)
-			if(q < 15 || ctlr->type != Type4965)
-				csr32w(ctlr, FhCbbcQueue + q*4, PCIWADDR(ctlr->tx[q].d) >> 8);
+		for(q = (ctlr->type != Type4965) ? 19 : 15; q >= 0; q--)
+			csr32w(ctlr, FhCbbcQueue + q*4, PCIWADDR(ctlr->tx[q].d) >> 8);
+
 		nicunlock(ctlr);
 
-		for(i=0; i<8; i++)
-			if(i < 7 || ctlr->type != Type4965)
-				csr32w(ctlr, FhTxConfig + i*32, FhTxConfigDmaEna | FhTxConfigDmaCreditEna);
+		for(i = (ctlr->type != Type4965) ? 7 : 6; i >= 0; i--)
+			csr32w(ctlr, FhTxConfig + i*32, FhTxConfigDmaEna | FhTxConfigDmaCreditEna);
 
 		csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill);
 		csr32w(ctlr, UcodeGp1Clr, UcodeGp1CmdBlocked);
@@ -1820,9 +1805,10 @@
 		case 192:	/* rx phy */
 			break;
 		case 195:	/* rx done */
-			if(d + 60 > b->lim)
+			if(d + 2 > b->lim)
 				break;
-			d += 60;
+			d += d[1];
+			d += 56;
 		case 193:	/* mpdu rx done */
 			if(d + 4 > b->lim)
 				break;
@@ -1906,6 +1892,8 @@
 		switch(pdev->did){
 		default:
 			continue;
+		case 0x4229:	/* WiFi Link 4965 */
+		case 0x4230:	/* WiFi Link 4965 */
 		case 0x4236:	/* WiFi Link 5300 AGN */
 		case 0x4237:	/* Wifi Link 5100 AGN */
 			break;
@@ -1940,7 +1928,7 @@
 		ctlr->pdev = pdev;
 		ctlr->type = (csr32r(ctlr, Rev) >> 4) & 0xF;
 
-		if(ctlrtype[ctlr->type].fwname == nil){
+		if(fwname[ctlr->type] == nil){
 			print("iwl: unsupported controller type %d\n", ctlr->type);
 			vunmap(mem, pdev->mem[0].size);
 			free(ctlr);