ref: 14b3bcbc4946c3e6947f9fdcec836defafaf05a9
parent: 70dfc2d75689339215d26637182830fc7348348b
author: cinap_lenrek <[email protected]>
date: Sat Nov 4 14:37:49 EDT 2023
devsd, sdmmc, ether4330: improve infrastructure for sdio devsd/sdmmc: provide annexsdio() function to take over a sdio controller from devsd. this removes the tight coupling between ether4330. devsd: get rid of legacy function pointer in SDifc struct. ether4330: cleanup code, fix bugs, set bus speed to 50Mhz, provide multicast and promiscuous mode support.
--- a/sys/src/9/bcm/emmc.c
+++ b/sys/src/9/bcm/emmc.c
@@ -267,8 +267,8 @@
intrenable(IRQmmc, emmcinterrupt, nil, BUSUNKNOWN, io->name);
}
-int
-sdiocardintr(int wait)
+static int
+emmccardintr(SDio*, int wait)
{
u32int *r = (u32int*)EMMCREGS;
int i;
@@ -458,7 +458,7 @@
}
-SDio sdio = {
+static SDio sdio = {
"emmc",
emmcinit,
emmcenable,
@@ -467,6 +467,7 @@
emmciosetup,
emmcio,
emmcbus,
+ emmccardintr,
};
void
--- a/sys/src/9/bcm/ether4330.c
+++ b/sys/src/9/bcm/ether4330.c
@@ -7,7 +7,6 @@
#include "mem.h"
#include "dat.h"
#include "fns.h"
-#include "io.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/sd.h"
@@ -15,12 +14,9 @@
#define CACHELINESZ 64 /* temp */
-extern SDio sdio;
-extern int sdiocardintr(int);
+static SDiocmd IO_SEND_OP_COND = { 5, 3, 0, 0, "IO_SEND_OP_COND" };
+static SDiocmd IO_RW_DIRECT = { 52, 1, 0, 0, "IO_RW_DIRECT" };
-SDiocmd IO_SEND_OP_COND = { 5, 3, 0, 0, "IO_SEND_OP_COND" };
-SDiocmd IO_RW_DIRECT = { 52, 1, 0, 0, "IO_RW_DIRECT" };
-
enum{
SDIODEBUG = 0,
SBDEBUG = 0,
@@ -152,11 +148,14 @@
struct WKey
{
ushort len;
- char dat[WKeyLen];
+ uchar dat[WKeyLen];
};
struct Ctlr {
- Ether* edev;
+ Ether *edev;
+ SDio *sdio;
+ int iodebug;
+ QLock sdiolock;
QLock cmdlock;
QLock pktlock;
QLock tlock;
@@ -263,7 +262,7 @@
static char config40181[] = "bcmdhd.cal.40181";
static char config40183[] = "bcmdhd.cal.40183.26MHz";
-struct {
+static struct {
int chipid;
int chiprev;
char *fwfile;
@@ -280,9 +279,6 @@
{ 0x4345, 9, "brcmfmac43456-sdio.bin", "brcmfmac43456-sdio.txt", "brcmfmac43456-sdio.clm_blob" },
};
-static QLock sdiolock;
-static int iodebug;
-
static void etherbcmintr(void *);
static void bcmevent(Ctlr*, uchar*, int);
static void wlscanresult(Ether*, uchar*, int);
@@ -335,50 +331,43 @@
* SDIO communication with dongle
*/
static ulong
-sdiocmd_locked(SDiocmd *cmd, ulong arg)
+sdiocmd(Ctlr *ctl, SDiocmd *cmd, ulong arg)
{
u32int resp[4];
+ SDio *io;
- sdio.cmd(&sdio, cmd, arg, resp);
- return resp[0];
-}
-
-static ulong
-sdiocmd(SDiocmd *cmd, ulong arg)
-{
- ulong r;
-
- qlock(&sdiolock);
+ qlock(&ctl->sdiolock);
if(waserror()){
if(SDIODEBUG) print("sdiocmd error: cmd %s arg %lux\n", cmd->name, arg);
- qunlock(&sdiolock);
+ qunlock(&ctl->sdiolock);
nexterror();
}
- r = sdiocmd_locked(cmd, arg);
- qunlock(&sdiolock);
+ io = ctl->sdio;
+ (*io->cmd)(io, cmd, arg, resp);
+ qunlock(&ctl->sdiolock);
poperror();
- return r;
+ return resp[0];
}
static ulong
-trysdiocmd(SDiocmd *cmd, ulong arg)
+trysdiocmd(Ctlr *ctl, SDiocmd *cmd, ulong arg)
{
ulong r;
if(waserror())
return 0;
- r = sdiocmd(cmd, arg);
+ r = sdiocmd(ctl, cmd, arg);
poperror();
return r;
}
static int
-sdiord(int fn, int addr)
+sdiord(Ctlr *ctl, int fn, int addr)
{
int r;
- r = sdiocmd(&IO_RW_DIRECT, (0<<31)|((fn&7)<<28)|((addr&0x1FFFF)<<9));
+ r = sdiocmd(ctl, &IO_RW_DIRECT, (0<<31)|((fn&7)<<28)|((addr&0x1FFFF)<<9));
if(r & 0xCF00){
print("ether4330: sdiord(%x, %x) fail: %2.2ux %2.2ux\n", fn, addr, (r>>8)&0xFF, r&0xFF);
error(Eio);
@@ -387,26 +376,14 @@
}
static void
-sdiowr(int fn, int addr, int data)
+sdiowr(Ctlr *ctl, int fn, int addr, int data)
{
int r;
int retry;
- ulong arg;
r = 0;
for(retry = 0; retry < 10; retry++){
- arg = (1<<31)|((fn&7)<<28)|((addr&0x1FFFF)<<9)|(data&0xFF);
- if((arg & ~0xFF) == (1<<31|0<<28|7<<9)){
- switch(arg&3){
- case 0:
- sdio.bus(&sdio, 1, 0);
- break;
- case 2:
- sdio.bus(&sdio, 4, 0);
- break;
- }
- }
- r = sdiocmd(&IO_RW_DIRECT, arg);
+ r = sdiocmd(ctl, &IO_RW_DIRECT, (1<<31)|((fn&7)<<28)|((addr&0x1FFFF)<<9)|(data&0xFF));
if((r & 0xCF00) == 0)
return;
}
@@ -415,10 +392,12 @@
}
static void
-sdiorwext(int fn, int write, void *a, int len, int addr, int incr)
+sdiorwext(Ctlr *ctl, int fn, int write, void *a, int len, int addr, int incr)
{
- int bsize, blk, bcount, m;
SDiocmd cmd = { 53, 1, 0, 0, "IO_RW_EXTENDED" };
+ int bsize, blk, bcount, m;
+ u32int resp[4];
+ SDio *io;
bsize = fn == Fn2? 512 : 64;
while(len > 0){
@@ -435,21 +414,22 @@
bcount = len;
m = bcount;
}
- qlock(&sdiolock);
+ qlock(&ctl->sdiolock);
if(waserror()){
print("ether4330: sdiorwext fail: %s\n", up->errstr);
- qunlock(&sdiolock);
+ qunlock(&ctl->sdiolock);
nexterror();
}
+ io = ctl->sdio;
cmd.data = write? 2 : 1; /* Host2card : Card2host */
if(blk){
cmd.data += 2; /* Multiblock | Blkcnten */
- sdio.iosetup(&sdio, write, a, bsize, bcount);
+ (*io->iosetup)(io, write, a, bsize, bcount);
}else
- sdio.iosetup(&sdio, write, a, bcount, 1);
- sdiocmd_locked(&cmd, write<<31 | (fn&7)<<28 | blk<<27 | incr<<26 | (addr&0x1FFFF)<<9 | (bcount&0x1FF));
- sdio.io(&sdio, write, a, m);
- qunlock(&sdiolock);
+ (*io->iosetup)(io, write, a, bcount, 1);
+ (*io->cmd)(io, &cmd, write<<31 | (fn&7)<<28 | blk<<27 | incr<<26 | (addr&0x1FFFF)<<9 | (bcount&0x1FF), resp);
+ (*io->io)(io, write, a, m);
+ qunlock(&ctl->sdiolock);
poperror();
len -= m;
a = (char*)a + m;
@@ -459,32 +439,37 @@
}
static void
-sdioset(int fn, int addr, int bits)
+sdioset(Ctlr *ctl, int fn, int addr, int bits)
{
- sdiowr(fn, addr, sdiord(fn, addr) | bits);
+ sdiowr(ctl, fn, addr, sdiord(ctl, fn, addr) | bits);
}
static void
-sdioinit(void)
+sdioinit(Ctlr *ctl)
{
ulong ocr, rca;
int i;
- /* disconnect emmc from SD card (connect sdhost instead) */
- for(i = 48; i <= 53; i++)
- gpiosel(i, Alt0);
- /* connect emmc to wifi */
- for(i = 34; i <= 39; i++){
- gpiosel(i, Alt3);
- if(i == 34)
- gpiopulloff(i);
- else
- gpiopullup(i);
+ if(ctl->sdio == nil){
+ /* take over /dev/sdN (emmc) */
+ ctl->sdio = annexsdio("N");
+
+ /* disconnect emmc from SD card (connect sdhost instead) */
+ for(i = 48; i <= 53; i++)
+ gpiosel(i, Alt0);
+ /* connect emmc to wifi */
+ for(i = 34; i <= 39; i++){
+ gpiosel(i, Alt3);
+ if(i == 34)
+ gpiopulloff(i);
+ else
+ gpiopullup(i);
+ }
}
- sdio.init(&sdio);
- sdio.enable(&sdio);
- sdiocmd(&GO_IDLE_STATE, 0);
- ocr = trysdiocmd(&IO_SEND_OP_COND, 0);
+ (*ctl->sdio->bus)(ctl->sdio, 1, SDfreq);
+
+ sdiocmd(ctl, &GO_IDLE_STATE, 0);
+ ocr = trysdiocmd(ctl, &IO_SEND_OP_COND, 0);
i = 0;
while((ocr & (1<<31)) == 0){
if(++i > 5){
@@ -491,21 +476,23 @@
print("ether4330: no response to sdio access: ocr = %lux\n", ocr);
error(Eio);
}
- ocr = trysdiocmd(&IO_SEND_OP_COND, V3_3);
+ ocr = trysdiocmd(ctl, &IO_SEND_OP_COND, V3_3);
tsleep(&up->sleep, return0, nil, 100);
}
- rca = sdiocmd(&SEND_RELATIVE_ADDR, 0) >> Rcashift;
- sdiocmd(&SELECT_CARD, rca << Rcashift);
- sdio.bus(&sdio, 0, SDfreq);
- sdioset(Fn0, Highspeed, 2);
- sdioset(Fn0, Busifc, 2); /* bus width 4 */
- sdiowr(Fn0, Fbr1+Blksize, 64);
- sdiowr(Fn0, Fbr1+Blksize+1, 64>>8);
- sdiowr(Fn0, Fbr2+Blksize, 512);
- sdiowr(Fn0, Fbr2+Blksize+1, 512>>8);
- sdioset(Fn0, Ioenable, 1<<Fn1);
- sdiowr(Fn0, Intenable, 0);
- for(i = 0; !(sdiord(Fn0, Ioready) & 1<<Fn1); i++){
+ rca = sdiocmd(ctl, &SEND_RELATIVE_ADDR, 0) >> Rcashift;
+ sdiocmd(ctl, &SELECT_CARD, rca << Rcashift);
+ sdioset(ctl, Fn0, Highspeed, 2);
+ sdioset(ctl, Fn0, Busifc, 2); /* bus width 4 */
+
+ (*ctl->sdio->bus)(ctl->sdio, 4, SDfreqhs);
+
+ sdiowr(ctl, Fn0, Fbr1+Blksize, 64);
+ sdiowr(ctl, Fn0, Fbr1+Blksize+1, 64>>8);
+ sdiowr(ctl, Fn0, Fbr2+Blksize, 512);
+ sdiowr(ctl, Fn0, Fbr2+Blksize+1, 512>>8);
+ sdioset(ctl, Fn0, Ioenable, 1<<Fn1);
+ sdiowr(ctl, Fn0, Intenable, 0);
+ for(i = 0; !(sdiord(ctl, Fn0, Ioready) & 1<<Fn1); i++){
if(i == 10){
print("ether4330: can't enable SDIO function\n");
error(Eio);
@@ -515,15 +502,15 @@
}
static void
-sdioreset(void)
+sdioreset(Ctlr *ctl)
{
- sdiowr(Fn0, Ioabort, 1<<3); /* reset */
+ sdiowr(ctl, Fn0, Ioabort, 1<<3); /* reset */
}
static void
-sdioabort(int fn)
+sdioabort(Ctlr *ctl, int fn)
{
- sdiowr(Fn0, Ioabort, fn);
+ sdiowr(ctl, Fn0, Ioabort, fn);
}
/*
@@ -531,19 +518,19 @@
*/
static void
-cfgw(ulong off, int val)
+cfgw(Ctlr *ctl, ulong off, int val)
{
- sdiowr(Fn1, off, val);
+ sdiowr(ctl, Fn1, off, val);
}
static int
-cfgr(ulong off)
+cfgr(Ctlr *ctl, ulong off)
{
- return sdiord(Fn1, off);
+ return sdiord(ctl, Fn1, off);
}
static ulong
-cfgreadl(int fn, ulong off)
+cfgreadl(Ctlr *ctl, int fn, ulong off)
{
uchar cbuf[2*CACHELINESZ];
uchar *p;
@@ -550,13 +537,13 @@
p = (uchar*)ROUND((uintptr)cbuf, CACHELINESZ);
memset(p, 0, 4);
- sdiorwext(fn, 0, p, 4, off|Sb32bit, 1);
+ sdiorwext(ctl, fn, 0, p, 4, off|Sb32bit, 1);
if(SDIODEBUG) print("cfgreadl %lux: %2.2x %2.2x %2.2x %2.2x\n", off, p[0], p[1], p[2], p[3]);
return p[0] | p[1]<<8 | p[2]<<16 | p[3]<<24;
}
static void
-cfgwritel(int fn, ulong off, u32int data)
+cfgwritel(Ctlr *ctl, int fn, ulong off, u32int data)
{
uchar cbuf[2*CACHELINESZ];
uchar *p;
@@ -568,25 +555,25 @@
retry = 0;
while(waserror()){
print("ether4330: cfgwritel retry %lux %ux\n", off, data);
- sdioabort(fn);
+ sdioabort(ctl, fn);
if(++retry == 3)
nexterror();
}
- sdiorwext(fn, 1, p, 4, off|Sb32bit, 1);
+ sdiorwext(ctl, fn, 1, p, 4, off|Sb32bit, 1);
poperror();
}
static void
-sbwindow(ulong addr)
+sbwindow(Ctlr *ctl, ulong addr)
{
addr &= ~(Sbwsize-1);
- cfgw(Sbaddr, addr>>8);
- cfgw(Sbaddr+1, addr>>16);
- cfgw(Sbaddr+2, addr>>24);
+ cfgw(ctl, Sbaddr, addr>>8);
+ cfgw(ctl, Sbaddr+1, addr>>16);
+ cfgw(ctl, Sbaddr+2, addr>>24);
}
static void
-sbrw(int fn, int write, uchar *buf, int len, ulong off)
+sbrw(Ctlr *ctl, int fn, int write, uchar *buf, int len, ulong off)
{
int n;
USED(fn);
@@ -599,13 +586,13 @@
if(len >= 4){
n = len;
n &= ~3;
- sdiorwext(Fn1, write, buf, n, off|Sb32bit, 1);
+ sdiorwext(ctl, Fn1, write, buf, n, off|Sb32bit, 1);
off += n;
buf += n;
len -= n;
}
while(len > 0){
- sdiowr(Fn1, off|Sb32bit, *buf);
+ sdiowr(ctl, Fn1, off|Sb32bit, *buf);
off++;
buf++;
len--;
@@ -614,13 +601,13 @@
if(len >= 4){
n = len;
n &= ~3;
- sdiorwext(Fn1, write, buf, n, off|Sb32bit, 1);
+ sdiorwext(ctl, Fn1, write, buf, n, off|Sb32bit, 1);
off += n;
buf += n;
len -= n;
}
while(len > 0){
- *buf = sdiord(Fn1, off|Sb32bit);
+ *buf = sdiord(ctl, Fn1, off|Sb32bit);
off++;
buf++;
len--;
@@ -630,7 +617,7 @@
}
static void
-sbmem(int write, uchar *buf, int len, ulong off)
+sbmem(Ctlr *ctl, int write, uchar *buf, int len, ulong off)
{
ulong n;
@@ -640,8 +627,8 @@
while(len > 0){
if(n > len)
n = len;
- sbwindow(off);
- sbrw(Fn1, write, buf, n, off & (Sbwsize-1));
+ sbwindow(ctl, off);
+ sbrw(ctl, Fn1, write, buf, n, off & (Sbwsize-1));
off += n;
buf += n;
len -= n;
@@ -650,7 +637,7 @@
}
static void
-packetrw(int write, uchar *buf, int len)
+packetrw(Ctlr *ctl, int write, uchar *buf, int len)
{
int n;
int retry;
@@ -661,11 +648,11 @@
n = ROUND(len, 4);
retry = 0;
while(waserror()){
- sdioabort(Fn2);
+ sdioabort(ctl, Fn2);
if(++retry == 3)
nexterror();
}
- sdiorwext(Fn2, write, buf, n, Enumbase, 0);
+ sdiorwext(ctl, Fn2, write, buf, n, Enumbase, 0);
poperror();
buf += n;
len -= n;
@@ -677,39 +664,41 @@
*/
static void
-sbdisable(ulong regs, int pre, int ioctl)
+sbdisable(Ctlr *ctl, ulong regs, int pre, int ioctl)
{
- sbwindow(regs);
- if((cfgreadl(Fn1, regs + Resetctrl) & 1) != 0){
- cfgwritel(Fn1, regs + Ioctrl, 3|ioctl);
- cfgreadl(Fn1, regs + Ioctrl);
+ sbwindow(ctl, regs);
+ if((cfgreadl(ctl, Fn1, regs + Resetctrl) & 1) != 0){
+ cfgwritel(ctl, Fn1, regs + Ioctrl, 3|ioctl);
+ cfgreadl(ctl, Fn1, regs + Ioctrl);
return;
}
- cfgwritel(Fn1, regs + Ioctrl, 3|pre);
- cfgreadl(Fn1, regs + Ioctrl);
- cfgwritel(Fn1, regs + Resetctrl, 1);
+ cfgwritel(ctl, Fn1, regs + Ioctrl, 3|pre);
+ cfgreadl(ctl, Fn1, regs + Ioctrl);
+ cfgwritel(ctl, Fn1, regs + Resetctrl, 1);
microdelay(10);
- while((cfgreadl(Fn1, regs + Resetctrl) & 1) == 0)
+ while((cfgreadl(ctl, Fn1, regs + Resetctrl) & 1) == 0)
;
- cfgwritel(Fn1, regs + Ioctrl, 3|ioctl);
- cfgreadl(Fn1, regs + Ioctrl);
+ cfgwritel(ctl, Fn1, regs + Ioctrl, 3|ioctl);
+ cfgreadl(ctl, Fn1, regs + Ioctrl);
}
static void
-sbreset(ulong regs, int pre, int ioctl)
+sbreset(Ctlr *ctl, ulong regs, int pre, int ioctl)
{
- sbdisable(regs, pre, ioctl);
- sbwindow(regs);
+ sbdisable(ctl, regs, pre, ioctl);
+ sbwindow(ctl, regs);
if(SBDEBUG) print("sbreset %#lux %#lux %#lux ->", regs,
- cfgreadl(Fn1, regs+Ioctrl), cfgreadl(Fn1, regs+Resetctrl));
- while((cfgreadl(Fn1, regs + Resetctrl) & 1) != 0){
- cfgwritel(Fn1, regs + Resetctrl, 0);
+ cfgreadl(ctl, Fn1, regs+Ioctrl),
+ cfgreadl(ctl, Fn1, regs+Resetctrl));
+ while((cfgreadl(ctl, Fn1, regs + Resetctrl) & 1) != 0){
+ cfgwritel(ctl, Fn1, regs + Resetctrl, 0);
microdelay(40);
}
- cfgwritel(Fn1, regs + Ioctrl, 1|ioctl);
- cfgreadl(Fn1, regs + Ioctrl);
+ cfgwritel(ctl, Fn1, regs + Ioctrl, 1|ioctl);
+ cfgreadl(ctl, Fn1, regs + Ioctrl);
if(SBDEBUG) print("%#lux %#lux\n",
- cfgreadl(Fn1, regs+Ioctrl), cfgreadl(Fn1, regs+Resetctrl));
+ cfgreadl(ctl, Fn1, regs+Ioctrl),
+ cfgreadl(ctl, Fn1, regs+Resetctrl));
}
static void
@@ -722,7 +711,7 @@
buf = sdmalloc(Corescansz);
if(buf == nil)
error(Enomem);
- sbmem(0, buf, Corescansz, r);
+ sbmem(ctl, 0, buf, Corescansz, r);
coreid = 0;
corerev = 0;
for(i = 0; i < Corescansz; i += 4){
@@ -788,14 +777,14 @@
if(ctl->armcore == ARMcr4){
r = ctl->armregs;
- sbwindow(r);
- n = cfgreadl(Fn1, r + Cr4Cap);
+ sbwindow(ctl, r);
+ n = cfgreadl(ctl, Fn1, r + Cr4Cap);
if(SBDEBUG) print("cr4 banks %lux\n", n);
banks = ((n>>4) & 0xF) + (n & 0xF);
size = 0;
for(i = 0; i < banks; i++){
- cfgwritel(Fn1, r + Cr4Bankidx, i);
- n = cfgreadl(Fn1, r + Cr4Bankinfo);
+ cfgwritel(ctl, Fn1, r + Cr4Bankidx, i);
+ n = cfgreadl(ctl, Fn1, r + Cr4Bankinfo);
if(SBDEBUG) print("bank %d reg %lux size %lud\n", i, n, 8192 * ((n & 0x3F) + 1));
size += 8192 * ((n & 0x3F) + 1);
}
@@ -807,16 +796,16 @@
print("ether4330: SOCRAM rev %d not supported\n", ctl->socramrev);
error(Eio);
}
- sbreset(ctl->socramctl, 0, 0);
+ sbreset(ctl, ctl->socramctl, 0, 0);
r = ctl->socramregs;
- sbwindow(r);
- n = cfgreadl(Fn1, r + Coreinfo);
+ sbwindow(ctl, r);
+ n = cfgreadl(ctl, Fn1, r + Coreinfo);
if(SBDEBUG) print("socramrev %d coreinfo %lux\n", ctl->socramrev, n);
banks = (n>>4) & 0xF;
size = 0;
for(i = 0; i < banks; i++){
- cfgwritel(Fn1, r + Bankidx, i);
- n = cfgreadl(Fn1, r + Bankinfo);
+ cfgwritel(ctl, Fn1, r + Bankidx, i);
+ n = cfgreadl(ctl, Fn1, r + Bankinfo);
if(SBDEBUG) print("bank %d reg %lux size %lud\n", i, n, 8192 * ((n & 0x3F) + 1));
size += 8192 * ((n & 0x3F) + 1);
}
@@ -823,8 +812,8 @@
ctl->socramsize = size;
ctl->rambase = 0;
if(ctl->chipid == 43430){
- cfgwritel(Fn1, r + Bankidx, 3);
- cfgwritel(Fn1, r + Bankpda, 0);
+ cfgwritel(ctl, Fn1, r + Bankidx, 3);
+ cfgwritel(ctl, Fn1, r + Bankpda, 0);
}
}
@@ -835,8 +824,8 @@
int chipid;
char buf[16];
- sbwindow(Enumbase);
- r = cfgreadl(Fn1, Enumbase);
+ sbwindow(ctl, Enumbase);
+ r = cfgreadl(ctl, Fn1, Enumbase);
chipid = r & 0xFFFF;
sprint(buf, chipid > 43000 ? "%d" : "%#x", chipid);
print("ether4330: chip %s rev %ld type %ld\n", buf, (r>>16)&0xF, (r>>28)&0xF);
@@ -852,40 +841,40 @@
print("ether4330: chipid %#x (%d) not supported\n", chipid, chipid);
error(Eio);
}
- r = cfgreadl(Fn1, Enumbase + 63*4);
+ r = cfgreadl(ctl, Fn1, Enumbase + 63*4);
corescan(ctl, r);
if(ctl->armctl == 0 || ctl->d11ctl == 0 ||
(ctl->armcore == ARMcm3 && (ctl->socramctl == 0 || ctl->socramregs == 0)))
error("corescan didn't find essential cores\n");
if(ctl->armcore == ARMcr4)
- sbreset(ctl->armctl, Cr4Cpuhalt, Cr4Cpuhalt);
+ sbreset(ctl, ctl->armctl, Cr4Cpuhalt, Cr4Cpuhalt);
else
- sbdisable(ctl->armctl, 0, 0);
- sbreset(ctl->d11ctl, 8|4, 4);
+ sbdisable(ctl, ctl->armctl, 0, 0);
+ sbreset(ctl, ctl->d11ctl, 8|4, 4);
ramscan(ctl);
if(SBDEBUG) print("ARM %#lux D11 %#lux SOCRAM %#lux,%#lux %lud bytes @ %#lux\n",
ctl->armctl, ctl->d11ctl, ctl->socramctl, ctl->socramregs, ctl->socramsize, ctl->rambase);
- cfgw(Clkcsr, 0);
+ cfgw(ctl, Clkcsr, 0);
microdelay(10);
- if(SBDEBUG) print("chipclk: %x\n", cfgr(Clkcsr));
- cfgw(Clkcsr, Nohwreq | ReqALP);
- while((cfgr(Clkcsr) & (HTavail|ALPavail)) == 0)
+ if(SBDEBUG) print("chipclk: %x\n", cfgr(ctl, Clkcsr));
+ cfgw(ctl, Clkcsr, Nohwreq | ReqALP);
+ while((cfgr(ctl, Clkcsr) & (HTavail|ALPavail)) == 0)
microdelay(10);
- cfgw(Clkcsr, Nohwreq | ForceALP);
+ cfgw(ctl, Clkcsr, Nohwreq | ForceALP);
microdelay(65);
- if(SBDEBUG) print("chipclk: %x\n", cfgr(Clkcsr));
- cfgw(Pullups, 0);
- sbwindow(ctl->chipcommon);
- cfgwritel(Fn1, ctl->chipcommon + Gpiopullup, 0);
- cfgwritel(Fn1, ctl->chipcommon + Gpiopulldown, 0);
+ if(SBDEBUG) print("chipclk: %x\n", cfgr(ctl, Clkcsr));
+ cfgw(ctl, Pullups, 0);
+ sbwindow(ctl, ctl->chipcommon);
+ cfgwritel(ctl, Fn1, ctl->chipcommon + Gpiopullup, 0);
+ cfgwritel(ctl, Fn1, ctl->chipcommon + Gpiopulldown, 0);
if(ctl->chipid != 0x4330 && ctl->chipid != 43362)
return;
- cfgwritel(Fn1, ctl->chipcommon + Chipctladdr, 1);
- if(cfgreadl(Fn1, ctl->chipcommon + Chipctladdr) != 1)
+ cfgwritel(ctl, Fn1, ctl->chipcommon + Chipctladdr, 1);
+ if(cfgreadl(ctl, Fn1, ctl->chipcommon + Chipctladdr) != 1)
print("ether4330: can't set Chipctladdr\n");
else{
- r = cfgreadl(Fn1, ctl->chipcommon + Chipctldata);
- if(SBDEBUG) print("chipcommon PMU (%lux) %lux", cfgreadl(Fn1, ctl->chipcommon + Chipctladdr), r);
+ r = cfgreadl(ctl, Fn1, ctl->chipcommon + Chipctldata);
+ if(SBDEBUG) print("chipcommon PMU (%lux) %lux", cfgreadl(ctl, Fn1, ctl->chipcommon + Chipctladdr), r);
/* set SDIO drive strength >= 6mA */
r &= ~0x3800;
if(ctl->chipid == 0x4330)
@@ -892,8 +881,8 @@
r |= 3<<11;
else
r |= 7<<11;
- cfgwritel(Fn1, ctl->chipcommon + Chipctldata, r);
- if(SBDEBUG) print("-> %lux (= %lux)\n", r, cfgreadl(Fn1, ctl->chipcommon + Chipctldata));
+ cfgwritel(ctl, Fn1, ctl->chipcommon + Chipctldata, r);
+ if(SBDEBUG) print("-> %lux (= %lux)\n", r, cfgreadl(ctl, Fn1, ctl->chipcommon + Chipctldata));
}
}
@@ -903,31 +892,33 @@
int i;
if(SBDEBUG) print("enabling HT clock...");
- cfgw(Clkcsr, 0);
+ cfgw(ctl, Clkcsr, 0);
delay(1);
- cfgw(Clkcsr, ReqHT);
- for(i = 0; (cfgr(Clkcsr) & HTavail) == 0; i++){
+ cfgw(ctl, Clkcsr, ReqHT);
+ for(i = 0; (cfgr(ctl, Clkcsr) & HTavail) == 0; i++){
if(i == 50){
- print("ether4330: can't enable HT clock: csr %x\n", cfgr(Clkcsr));
+ print("ether4330: can't enable HT clock: csr %x\n",
+ cfgr(ctl, Clkcsr));
error(Eio);
}
tsleep(&up->sleep, return0, nil, 100);
}
- cfgw(Clkcsr, cfgr(Clkcsr) | ForceHT);
+ cfgw(ctl, Clkcsr, cfgr(ctl, Clkcsr) | ForceHT);
delay(10);
- if(SBDEBUG) print("chipclk: %x\n", cfgr(Clkcsr));
- sbwindow(ctl->sdregs);
- cfgwritel(Fn1, ctl->sdregs + Sbmboxdata, 4 << 16); /* protocol version */
- cfgwritel(Fn1, ctl->sdregs + Intmask, FrameInt | MailboxInt | Fcchange);
- sdioset(Fn0, Ioenable, 1<<Fn2);
- for(i = 0; !(sdiord(Fn0, Ioready) & 1<<Fn2); i++){
+ if(SBDEBUG) print("chipclk: %x\n", cfgr(ctl, Clkcsr));
+ sbwindow(ctl, ctl->sdregs);
+ cfgwritel(ctl, Fn1, ctl->sdregs + Sbmboxdata, 4 << 16); /* protocol version */
+ cfgwritel(ctl, Fn1, ctl->sdregs + Intmask, FrameInt | MailboxInt | Fcchange);
+ sdioset(ctl, Fn0, Ioenable, 1<<Fn2);
+ for(i = 0; !(sdiord(ctl, Fn0, Ioready) & 1<<Fn2); i++){
if(i == 10){
- print("ether4330: can't enable SDIO function 2 - ioready %x\n", sdiord(Fn0, Ioready));
+ print("ether4330: can't enable SDIO function 2 - ioready %x\n",
+ sdiord(ctl, Fn0, Ioready));
error(Eio);
}
tsleep(&up->sleep, return0, nil, 100);
}
- sdiowr(Fn0, Intenable, (1<<Fn1) | (1<<Fn2) | 1);
+ sdiowr(ctl, Fn0, Intenable, (1<<Fn1) | (1<<Fn2) | 1);
}
@@ -1045,7 +1036,7 @@
memmove(ctl->resetvec.c, buf, sizeof(ctl->resetvec.c));
while(n&3)
buf[n++] = 0;
- sbmem(1, buf, n, ctl->rambase + off);
+ sbmem(ctl, 1, buf, n, ctl->rambase + off);
if(isconfig)
break;
off += n;
@@ -1062,7 +1053,7 @@
while(n&3)
buf[n++] = 0;
}
- sbmem(0, cbuf, n, ctl->rambase + off);
+ sbmem(ctl, 0, cbuf, n, ctl->rambase + off);
if(memcmp(buf, cbuf, n) != 0){
print("ether4330: firmware load failed offset %d\n", off);
error(Eio);
@@ -1152,11 +1143,11 @@
}
}
ctl->regufile = firmware[i].regufile;
- cfgw(Clkcsr, ReqALP);
- while((cfgr(Clkcsr) & ALPavail) == 0)
+ cfgw(ctl, Clkcsr, ReqALP);
+ while((cfgr(ctl, Clkcsr) & ALPavail) == 0)
microdelay(10);
memset(buf, 0, 4);
- sbmem(1, buf, 4, ctl->rambase + ctl->socramsize - 4);
+ sbmem(ctl, 1, buf, 4, ctl->rambase + ctl->socramsize - 4);
if(FWDEBUG) print("firmware load...");
upload(ctl, firmware[i].fwfile, 0);
if(FWDEBUG) print("config load...");
@@ -1164,17 +1155,17 @@
n /= 4;
n = (n & 0xFFFF) | (~n << 16);
put4(buf, n);
- sbmem(1, buf, 4, ctl->rambase + ctl->socramsize - 4);
+ sbmem(ctl, 1, buf, 4, ctl->rambase + ctl->socramsize - 4);
if(ctl->armcore == ARMcr4){
- sbwindow(ctl->sdregs);
- cfgwritel(Fn1, ctl->sdregs + Intstatus, ~0);
+ sbwindow(ctl, ctl->sdregs);
+ cfgwritel(ctl, Fn1, ctl->sdregs + Intstatus, ~0);
if(ctl->resetvec.i != 0){
if(SBDEBUG) print("%ux\n", ctl->resetvec.i);
- sbmem(1, ctl->resetvec.c, sizeof(ctl->resetvec.c), 0);
+ sbmem(ctl, 1, ctl->resetvec.c, sizeof(ctl->resetvec.c), 0);
}
- sbreset(ctl->armctl, Cr4Cpuhalt, 0);
+ sbreset(ctl, ctl->armctl, Cr4Cpuhalt, 0);
}else
- sbreset(ctl->armctl, 0, 0);
+ sbreset(ctl, ctl->armctl, 0, 0);
}
/*
@@ -1181,8 +1172,8 @@
* Communication of data and control packets
*/
-void
-intwait(Ctlr *ctlr, int wait)
+static void
+intwait(Ctlr *ctl, int wait)
{
ulong ints, mbox;
int i;
@@ -1190,19 +1181,20 @@
if(waserror())
return;
for(;;){
- sdiocardintr(wait);
- sbwindow(ctlr->sdregs);
- i = sdiord(Fn0, Intpend);
+ if(ctl->sdio->cardintr != nil)
+ (*ctl->sdio->cardintr)(ctl->sdio, wait);
+ sbwindow(ctl, ctl->sdregs);
+ i = sdiord(ctl, Fn0, Intpend);
if(i == 0){
tsleep(&up->sleep, return0, 0, 10);
continue;
}
- ints = cfgreadl(Fn1, ctlr->sdregs + Intstatus);
- cfgwritel(Fn1, ctlr->sdregs + Intstatus, ints);
- if(0) print("INTS: (%x) %lux -> %lux\n", i, ints, cfgreadl(Fn1, ctlr->sdregs + Intstatus));
+ ints = cfgreadl(ctl, Fn1, ctl->sdregs + Intstatus);
+ cfgwritel(ctl, Fn1, ctl->sdregs + Intstatus, ints);
+ if(0) print("INTS: (%x) %lux -> %lux\n", i, ints, cfgreadl(ctl, Fn1, ctl->sdregs + Intstatus));
if(ints & MailboxInt){
- mbox = cfgreadl(Fn1, ctlr->sdregs + Hostmboxdata);
- cfgwritel(Fn1, ctlr->sdregs + Sbmbox, 2); /* ack */
+ mbox = cfgreadl(ctl, Fn1, ctl->sdregs + Hostmboxdata);
+ cfgwritel(ctl, Fn1, ctl->sdregs + Sbmbox, 2); /* ack */
if(mbox & 0x8)
print("ether4330: firmware ready\n");
}
@@ -1223,7 +1215,7 @@
p = (Sdpcm*)b->wp;
qlock(&ctl->pktlock);
for(;;){
- packetrw(0, b->wp, Sdpcmsz);
+ packetrw(ctl, 0, b->wp, Sdpcmsz);
len = p->len[0] | p->len[1]<<8;
if(len == 0){
freeb(b);
@@ -1234,15 +1226,15 @@
if(lenck != (len ^ 0xFFFF) ||
len < Sdpcmsz || len > 2048){
print("ether4330: wlreadpkt error len %.4x lenck %.4x\n", len, lenck);
- cfgw(Framectl, Rfhalt);
- while(cfgr(Rfrmcnt+1))
+ cfgw(ctl, Framectl, Rfhalt);
+ while(cfgr(ctl, Rfrmcnt+1))
;
- while(cfgr(Rfrmcnt))
+ while(cfgr(ctl, Rfrmcnt))
;
continue;
}
if(len > Sdpcmsz)
- packetrw(0, b->wp + Sdpcmsz, len - Sdpcmsz);
+ packetrw(ctl, 0, b->wp + Sdpcmsz, len - Sdpcmsz);
b->wp += len;
break;
}
@@ -1292,19 +1284,20 @@
p->seq = ctl->txseq;
p->doffset = off;
put4(b->rp + off, 0x20); /* BDC header */
- if(iodebug) dump("send", b->rp, len);
+ if(ctl->iodebug) dump("send", b->rp, len);
qlock(&ctl->pktlock);
if(waserror()){
- if(iodebug) print("halt frame %x %x\n", cfgr(Wfrmcnt+1), cfgr(Wfrmcnt+1));
- cfgw(Framectl, Wfhalt);
- while(cfgr(Wfrmcnt+1))
+ if(ctl->iodebug) print("halt frame %x %x\n",
+ cfgr(ctl, Wfrmcnt+1), cfgr(ctl, Wfrmcnt+1));
+ cfgw(ctl, Framectl, Wfhalt);
+ while(cfgr(ctl, Wfrmcnt+1))
;
- while(cfgr(Wfrmcnt))
+ while(cfgr(ctl, Wfrmcnt))
;
qunlock(&ctl->pktlock);
nexterror();
}
- packetrw(1, b->rp, len);
+ packetrw(ctl, 1, b->rp, len);
ctl->txseq++;
poperror();
qunlock(&ctl->pktlock);
@@ -1356,7 +1349,7 @@
}
switch(p->chanflg & 0xF){
case 0:
- if(iodebug) dump("rsp", b->rp, BLEN(b));
+ if(ctl->iodebug) dump("rsp", b->rp, BLEN(b));
if(BLEN(b) < Sdpcmsz + Cmdsz)
break;
q = (Cmd*)(b->rp + Sdpcmsz);
@@ -1366,7 +1359,7 @@
wakeup(&ctl->cmdr);
continue;
case 1:
- if(iodebug) dump("event", b->rp, BLEN(b));
+ if(ctl->iodebug) dump("event", b->rp, BLEN(b));
if(BLEN(b) > p->doffset + 4){
bdc = 4 + (b->rp[p->doffset + 3] << 2);
if(BLEN(b) > p->doffset + bdc){
@@ -1375,11 +1368,11 @@
break;
}
}
- if(iodebug && BLEN(b) != p->doffset)
+ if(ctl->iodebug && BLEN(b) != p->doffset)
print("short event %lld %d\n", BLEN(b), p->doffset);
break;
case 2:
- if(iodebug) dump("packet", b->rp, BLEN(b));
+ if(ctl->iodebug) dump("packet", b->rp, BLEN(b));
if(BLEN(b) > p->doffset + 4){
bdc = 4 + (b->rp[p->doffset + 3] << 2);
if(BLEN(b) >= p->doffset + bdc + ETHERHDRSIZE){
@@ -1645,8 +1638,8 @@
memmove(b->wp + dlen, res, rlen);
b->wp += tlen;
- if(iodebug) dump("cmd", b->rp, len);
- packetrw(1, b->rp, len);
+ if(ctl->iodebug) dump("cmd", b->rp, len);
+ packetrw(ctl, 1, b->rp, len);
ctl->txseq++;
qunlock(&ctl->pktlock);
freeb(b);
@@ -1990,6 +1983,20 @@
}
static void
+rxmode(Ether *edev, int prom)
+{
+ Ctlr *ctlr = edev->ctlr;
+
+ wlsetint(ctlr, "allmulti", edev->nmaddr > 0);
+
+ /* SET_PROMISC */
+ wlcmdint(ctlr, 10, prom);
+
+ wlsetint(ctlr, "arp_ol", !prom);
+ wlsetint(ctlr, "ndoe", !prom);
+}
+
+static void
wlinit(Ether *edev, Ctlr *ctlr)
{
uchar ea[Eaddrlen];
@@ -2036,7 +2043,9 @@
if(0) print("ether4330: %s\n", version);
wlsetint(ctlr, "roam_off", 1);
wlcmdint(ctlr, 0x14, 1); /* SET_INFRA 1 */
- wlcmdint(ctlr, 10, 0); /* SET_PROMISC */
+
+ rxmode(edev, edev->prom);
+
//wlcmdint(ctlr, 0x8e, 0); /* SET_BAND 0 */
//wlsetint(ctlr, "wsec", 1);
wlcmdint(ctlr, 2, 1); /* UP */
@@ -2051,7 +2060,7 @@
static long
etherbcmifstat(Ether* edev, void* a, long n, ulong offset)
{
- Ctlr *ctlr;
+ Ctlr *ctl;
char *p;
int l;
static char *cryptoname[4] = {
@@ -2067,19 +2076,19 @@
[Connected] = "associated",
};
- ctlr = edev->ctlr;
- if(ctlr == nil)
+ ctl = edev->ctlr;
+ if(ctl == nil)
return 0;
p = malloc(READSTR);
l = 0;
- l += snprint(p+l, READSTR-l, "channel: %d\n", ctlr->chanid);
- l += snprint(p+l, READSTR-l, "essid: %s\n", ctlr->essid);
- l += snprint(p+l, READSTR-l, "crypt: %s\n", cryptoname[ctlr->cryptotype]);
+ l += snprint(p+l, READSTR-l, "channel: %d\n", ctl->chanid);
+ l += snprint(p+l, READSTR-l, "essid: %s\n", ctl->essid);
+ l += snprint(p+l, READSTR-l, "crypt: %s\n", cryptoname[ctl->cryptotype]);
l += snprint(p+l, READSTR-l, "oq: %d\n", qlen(edev->oq));
- l += snprint(p+l, READSTR-l, "txwin: %d\n", ctlr->txwindow);
- l += snprint(p+l, READSTR-l, "txseq: %d\n", ctlr->txseq);
- l += snprint(p+l, READSTR-l, "status: %s\n", connectstate[ctlr->status]);
+ l += snprint(p+l, READSTR-l, "txwin: %d\n", ctl->txwindow);
+ l += snprint(p+l, READSTR-l, "txseq: %d\n", ctl->txseq);
+ l += snprint(p+l, READSTR-l, "status: %s\n", connectstate[ctl->status]);
USED(l);
n = readstr(offset, a, n, p);
free(p);
@@ -2089,106 +2098,55 @@
static void
etherbcmtransmit(Ether *edev)
{
- Ctlr *ctlr;
-
- ctlr = edev->ctlr;
- if(ctlr == nil)
+ if(edev->ctlr == nil)
return;
txstart(edev);
}
static int
-parsehex(char *buf, int buflen, char *a)
+wepparsekey(WKey* key, char *s)
{
- int i, k, n;
+ uchar buf[WMaxKeyLen];
+ int len;
- k = 0;
- for(i = 0;k < buflen && *a; i++){
- if(*a >= '0' && *a <= '9')
- n = *a++ - '0';
- else if(*a >= 'a' && *a <= 'f')
- n = *a++ - 'a' + 10;
- else if(*a >= 'A' && *a <= 'F')
- n = *a++ - 'A' + 10;
- else
- break;
-
- if(i & 1){
- buf[k] |= n;
- k++;
- }
- else
- buf[k] = n<<4;
- }
- if(i & 1)
- return -1;
- return k;
-}
-
-static int
-wepparsekey(WKey* key, char* a)
-{
- int i, k, len, n;
- char buf[WMaxKeyLen];
-
- len = strlen(a);
+ len = strlen(s);
if(len == WMinKeyLen || len == WMaxKeyLen){
- memset(key->dat, 0, sizeof(key->dat));
- memmove(key->dat, a, len);
key->len = len;
-
+ memmove(key->dat, s, len);
return 0;
}
else if(len == WMinKeyLen*2 || len == WMaxKeyLen*2){
- k = 0;
- for(i = 0; i < len; i++){
- if(*a >= '0' && *a <= '9')
- n = *a++ - '0';
- else if(*a >= 'a' && *a <= 'f')
- n = *a++ - 'a' + 10;
- else if(*a >= 'A' && *a <= 'F')
- n = *a++ - 'A' + 10;
- else
- return -1;
-
- if(i & 1){
- buf[k] |= n;
- k++;
- }
- else
- buf[k] = n<<4;
+ len /= 2;
+ if(dec16(buf, len, s, len*2) == len){
+ key->len = len;
+ memmove(key->dat, buf, len);
+ memset(buf, 0, sizeof buf);
+ return 0;
}
-
- memset(key->dat, 0, sizeof(key->dat));
- memmove(key->dat, buf, k);
- key->len = k;
-
- return 0;
}
-
return -1;
}
static int
-wpaparsekey(WKey *key, uvlong *ivp, char *a)
+wpaparsekey(WKey *key, uvlong *ivp, char *s)
{
+ uchar buf[WKeyLen];
int len;
char *e;
- if(cistrncmp(a, "tkip:", 5) == 0 || cistrncmp(a, "ccmp:", 5) == 0)
- a += 5;
+ if(cistrncmp(s, "tkip:", 5) == 0 || cistrncmp(s, "ccmp:", 5) == 0)
+ s += 5;
else
return 1;
- len = parsehex(key->dat, sizeof(key->dat), a);
+ if((e = strchr(s, '@')) == nil)
+ return 1;
+ len = dec16(buf, sizeof buf, s, e - s);
if(len <= 0)
return 1;
key->len = len;
- a += 2*len;
- if(*a++ != '@')
- return 1;
- *ivp = strtoull(a, &e, 16);
- if(e == a)
- return -1;
+ memmove(key->dat, buf, len);
+ memset(buf, 0, sizeof buf);
+ *ivp = strtoull(++e, nil, 16);
return 0;
}
@@ -2198,7 +2156,7 @@
uchar wpaie[32];
int i;
- i = parsehex((char*)wpaie, sizeof wpaie, a);
+ i = dec16(wpaie, sizeof wpaie, a, strlen(a));
if(i < 2 || i != wpaie[1] + 2)
cmderror(cb, "bad wpa ie syntax");
if(wpaie[0] == 0xdd)
@@ -2310,6 +2268,7 @@
i = ct->index - CMkey1;
if(wepparsekey(&ctlr->keys[i], cb->f[1]))
cmderror(cb, "bad WEP key syntax");
+ memset(cb->f[1], 0, strlen(cb->f[1]));
wlsetint(ctlr, "wsec", 1); /* wep enabled */
wlwepkey(ctlr, i);
break;
@@ -2323,10 +2282,11 @@
cmderror(cb, "bad ether addr");
if(wpaparsekey(&ctlr->keys[0], &iv, cb->f[2]))
cmderror(cb, "bad wpa key");
+ memset(cb->f[2], 0, strlen(cb->f[2]));
wlwpakey(ctlr, ct->index, iv, ea);
break;
case CMdebug:
- iodebug = atoi(cb->f[1]);
+ ctlr->iodebug = atoi(cb->f[1]);
break;
}
poperror();
@@ -2348,40 +2308,55 @@
static void
etherbcmattach(Ether* edev)
{
- Ctlr *ctlr;
+ Ctlr *ctl;
- ctlr = edev->ctlr;
- qlock(&ctlr->alock);
+ ctl = edev->ctlr;
+ qlock(&ctl->alock);
if(waserror()){
- //print("ether4330: attach failed: %s\n", up->errstr);
- qunlock(&ctlr->alock);
+ qunlock(&ctl->alock);
nexterror();
}
- if(ctlr->edev == nil){
- if(ctlr->chipid == 0){
- sdioinit();
- sbinit(ctlr);
+ if(ctl->edev == nil){
+ if(ctl->chipid == 0){
+ sdioinit(ctl);
+ sbinit(ctl);
}
- fwload(ctlr);
- sbenable(ctlr);
+ fwload(ctl);
+ sbenable(ctl);
+ ctl->edev = edev;
kproc("wifireader", rproc, edev);
kproc("wifitimer", lproc, edev);
- if(ctlr->regufile)
- reguload(ctlr, ctlr->regufile);
- wlinit(edev, ctlr);
- ctlr->edev = edev;
+ if(ctl->regufile)
+ reguload(ctl, ctl->regufile);
+ wlinit(edev, ctl);
}
- qunlock(&ctlr->alock);
+ qunlock(&ctl->alock);
poperror();
}
static void
-etherbcmshutdown(Ether*)
+etherbcmshutdown(Ether *edev)
{
- sdioreset();
+ Ctlr *ctl = edev->ctlr;
+
+ if(ctl->sdio != nil)
+ sdioreset(ctl);
}
+static void
+etherbcmprom(void *arg, int on)
+{
+ Ether *edev = arg;
+ rxmode(edev, on);
+}
+static void
+etherbcmmulti(void *arg, uchar*, int)
+{
+ Ether *edev = arg;
+ rxmode(edev, edev->prom);
+}
+
static int
etherbcmpnp(Ether* edev)
{
@@ -2399,6 +2374,8 @@
edev->ctl = etherbcmctl;
edev->scanbs = etherbcmscan;
edev->shutdown = etherbcmshutdown;
+ edev->promiscuous = etherbcmprom;
+ edev->multicast = etherbcmmulti;
edev->arg = edev;
return 0;
--- a/sys/src/9/bcm64/pi4
+++ b/sys/src/9/bcm64/pi4
@@ -32,13 +32,14 @@
archbcm4 pci
usbxhcipci pci usbxhci archbcm4
ethergenet ethermii
- ether4330 emmc
+ ether4330
ethermedium
loopbackmedium
netdevmedium
- sdhc
# i2cbcm devi2c
i2cgpio devi2c gpio
+ sdhc
+ emmc
ip
tcp
@@ -53,7 +54,7 @@
misc
uartmini
uartpl011
- sdmmc sdhc
+ sdmmc sdhc emmc
dma
gic
vcore
--- a/sys/src/9/pc/sd53c8xx.c
+++ b/sys/src/9/pc/sd53c8xx.c
@@ -2231,7 +2231,6 @@
"53c8xx", /* name */
sd53c8xxpnp, /* pnp */
- nil, /* legacy */
sd53c8xxenable, /* enable */
nil, /* disable */
--- a/sys/src/9/pc/sdiahci.c
+++ b/sys/src/9/pc/sdiahci.c
@@ -2520,7 +2520,6 @@
"ahci",
iapnp,
- nil, /* legacy */
iaenable,
iadisable,
--- a/sys/src/9/pc/sdide.c
+++ b/sys/src/9/pc/sdide.c
@@ -2431,7 +2431,6 @@
"ide", /* name */
atapnp, /* pnp */
- nil, /* legacy */
ataenable, /* enable */
atadisable, /* disable */
--- a/sys/src/9/pc/sdmylex.c
+++ b/sys/src/9/pc/sdmylex.c
@@ -1247,7 +1247,6 @@
"mylex", /* name */
mylexpnp, /* pnp */
- nil, /* legacy */
mylexenable, /* enable */
nil, /* disable */
--- a/sys/src/9/pc/sdodin.c
+++ b/sys/src/9/pc/sdodin.c
@@ -2828,7 +2828,6 @@
SDifc sdodinifc = {
"odin",
mspnp,
- nil,
msenable,
msdisable,
msverify,
--- a/sys/src/9/pc/sdvirtio.c
+++ b/sys/src/9/pc/sdvirtio.c
@@ -683,7 +683,6 @@
"virtio", /* name */
viopnp, /* pnp */
- nil, /* legacy */
vioenable, /* enable */
viodisable, /* disable */
--- a/sys/src/9/port/devsd.c
+++ b/sys/src/9/port/devsd.c
@@ -110,6 +110,20 @@
}
static void
+freesdev(SDev *sdev)
+{
+ int i;
+
+ /* free units and their files */
+ for(i = 0; i < sdev->nunit; i++)
+ freeunit(sdev->unit[i]);
+
+ free(sdev->unitflg);
+ free(sdev->unit);
+ free(sdev);
+}
+
+static void
sdaddpart(SDunit* unit, char* name, uvlong start, uvlong end)
{
SDpart *pp;
@@ -393,7 +407,7 @@
continue;
}
id = sdindex(sdev->idno);
- if(id == -1){
+ if(id < 0){
print("sdadddevs: bad id number %d (%C)\n", id, id);
goto giveup;
}
@@ -1653,14 +1667,8 @@
if(sdev->ifc->clear != nil)
(*sdev->ifc->clear)(sdev);
- /* free units and their files */
- for(i = 0; i < sdev->nunit; i++)
- freeunit(sdev->unit[i]);
+ freesdev(sdev);
- free(sdev->unitflg);
- free(sdev->unit);
- free(sdev);
-
return 0;
}
@@ -1717,6 +1725,46 @@
}
(*sdev->ifc->disable)(sdev);
}
+}
+
+/*
+ * find a SDdev, make sure its enabled and free it,
+ * returning its controller. This is used by
+ * annexsdio() to take over sdio from devsd.
+ */
+void*
+sdannexctlr(char *spec, SDifc *ifc)
+{
+ int i;
+ SDev *sdev;
+ void *ctlr;
+
+ if((i = sdindex(*spec)) < 0)
+ error(Enonexist);
+
+ qlock(&devslock);
+ if((sdev = devs[i]) == nil){
+ qunlock(&devslock);
+ error(Enonexist);
+ }
+ if(sdev->ifc != ifc){
+ qunlock(&devslock);
+ error(Enonexist);
+ }
+ if(sdev->r.ref){
+ qunlock(&devslock);
+ error(Einuse);
+ }
+ devs[i] = nil;
+ qunlock(&devslock);
+
+ if(!sdev->enabled && ifc->enable != nil)
+ (*ifc->enable)(sdev);
+
+ ctlr = sdev->ctlr;
+ freesdev(sdev);
+
+ return ctlr;
}
Dev sddevtab = {
--- a/sys/src/9/port/sd.h
+++ b/sys/src/9/port/sd.h
@@ -81,7 +81,6 @@
char* name;
SDev* (*pnp)(void);
- SDev* (*xxlegacy)(int, int); /* unused. remove me */
int (*enable)(SDev*);
int (*disable)(SDev*);
@@ -198,11 +197,13 @@
void (*iosetup)(SDio*, int, void*, int, int);
void (*io)(SDio*, int, uchar*, int);
void (*bus)(SDio*, int, int);
+ int (*cardintr)(SDio*, int);
char nomultiwrite; /* quirk for usdhc */
void *aux;
};
extern void addmmcio(SDio *io);
+extern SDio* annexsdio(char*);
/* devsd.c */
extern void sdadddevs(SDev*);
@@ -210,6 +211,7 @@
extern int sdfakescsi(SDreq*);
extern int sdfakescsirw(SDreq*, uvlong*, int*, int*);
extern int sdaddfile(SDunit*, char*, int, char*, SDrw*, SDrw*);
+extern void* sdannexctlr(char*, SDifc*);
/* sdscsi.c */
extern int scsiverify(SDunit*);
--- a/sys/src/9/port/sdaoe.c
+++ b/sys/src/9/port/sdaoe.c
@@ -521,7 +521,6 @@
"aoe",
aoepnp,
- nil, /* legacy */
nil, /* enable */
nil, /* disable */
--- a/sys/src/9/port/sdloop.c
+++ b/sys/src/9/port/sdloop.c
@@ -383,7 +383,6 @@
"loop",
pnp,
- nil, /* legacy */
nil, /* enable */
nil, /* disable */
--- a/sys/src/9/port/sdmmc.c
+++ b/sys/src/9/port/sdmmc.c
@@ -184,7 +184,35 @@
return list;
}
+static SDio*
+freecard(Card *card)
+{
+ SDio *io = card->io;
+
+ /* wait for retryproc() */
+ do {
+ qlock(card);
+ qunlock(card);
+ } while(card->retry);
+
+ free(card);
+
+ return io;
+}
+
+SDio*
+annexsdio(char *spec)
+{
+ return freecard(sdannexctlr(spec, &sdmmcifc));
+}
+
static void
+mmcclear(SDev *sdev)
+{
+ free(freecard(sdev->ctlr));
+}
+
+static void
readextcsd(Card *card)
{
SDio *io = card->io;
@@ -716,4 +744,5 @@
.rctl = mmcrctl,
.bio = mmcbio,
.rio = mmcrio,
+ .clear = mmcclear,
};
--- a/sys/src/9/port/sdnvme.c
+++ b/sys/src/9/port/sdnvme.c
@@ -785,7 +785,6 @@
"nvme", /* name */
nvmepnp, /* pnp */
- nil, /* legacy */
nvmeenable, /* enable */
nvmedisable, /* disable */
--- a/sys/src/9/port/sdvirtio10.c
+++ b/sys/src/9/port/sdvirtio10.c
@@ -792,7 +792,6 @@
"virtio10", /* name */
viopnp, /* pnp */
- nil, /* legacy */
vioenable, /* enable */
viodisable, /* disable */
--- a/sys/src/9/xen/sdxen.c
+++ b/sys/src/9/xen/sdxen.c
@@ -339,7 +339,6 @@
"xen", /* name */
xenpnp, /* pnp */
- 0, /* legacy */
0, /* enable */
0, /* disable */