#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#include "../port/error.h"#include "../port/netif.h" #include "etherif.h"#include "wifi.h" enum { Nrxlog = 6, Nrx = 1<<Nrxlog, Ntx = 256, Rbufsize = 3*1024, Rdscsize = 8, Tdscsize = 64, Tcmdsize = 128,}; /* registers */enum { Cfg = 0x000, AlmMb = 1<<8, AlmMm = 1<<9, SkuMrc = 1<<10, RevD = 1<<11, TypeB = 1<<12, Isr = 0x008, Imr = 0x00c, Ialive = 1<<0, Iwakeup = 1<<1, Iswrx = 1<<3, Irftoggled = 1<<7, Iswerr = 1<<25, Ifhtx = 1<<27, Ihwerr = 1<<29, Ifhrx = 1<<31, Ierr = Iswerr | Ihwerr, Idefmask = Ierr | Ifhtx | Ifhrx | Ialive | Iwakeup | Iswrx | Irftoggled, FhIsr = 0x010, GpioIn = 0x018, Reset = 0x020, Nevo = 1<<0, SW = 1<<7, MasterDisabled = 1<<8, StopMaster = 1<<9, Gpc = 0x024, MacAccessEna = 1<<0, MacClockReady = 1<<0, InitDone = 1<<2, MacAccessReq = 1<<3, NicSleep = 1<<4, RfKill = 1<<27, Eeprom = 0x02c, EepromGp = 0x030, UcodeGp1Clr = 0x05c, UcodeGp1RfKill = 1<<1, UcodeGp1CmdBlocked = 1<<2, UcodeGp2 = 0x060, GioChicken = 0x100, L1AnoL0Srx = 1<<23, AnaPll = 0x20c, Init = 1<<24, PrphWaddr = 0x444, PrphRaddr = 0x448, PrphWdata = 0x44c, PrphRdata = 0x450, HbusTargWptr = 0x460,}; /* * Flow-Handler registers. */enum { FhCbbcCtrl = 0x940, FhCbbcBase = 0x944, FhRxConfig = 0xc00, FhRxConfigDmaEna = 1<<31, FhRxConfigRdrbdEna = 1<<29, FhRxConfigWrstatusEna = 1<<27, FhRxConfigMaxfrag = 1<<24, FhRxConfigIrqDstHost = 1<<12, FhRxConfigNrdbShift = 20, FhRxConfigIrqRbthShift = 4, FhRxBase = 0xc04, FhRxWptr = 0xc20, FhRxRptrAddr = 0xc24, FhRssrTbl = 0xcc0, FhRxStatus = 0xcc4, FhTxConfig = 0xd00, // +q*32 FhTxBase = 0xe80, FhMsgConfig = 0xe88, FhTxStatus = 0xe90,}; /* * NIC internal memory offsets. */enum { AlmSchedMode = 0x2e00, AlmSchedArastat = 0x2e04, AlmSchedTxfact = 0x2e10, AlmSchedTxf4mf = 0x2e14, AlmSchedTxf5mf = 0x2e20, AlmSchedBP1 = 0x2e2c, AlmSchedBP2 = 0x2e30, ApmgClkEna = 0x3004, ApmgClkDis = 0x3008, DmaClkRqt = 1<<9, BsmClkRqt = 1<<11, ApmgPs = 0x300c, PwrSrcVMain = 0<<24, PwrSrcMask = 3<<24, ApmgPciStt = 0x3010, BsmWrCtrl = 0x3400, BsmWrMemSrc = 0x3404, BsmWrMemDst = 0x3408, BsmWrDwCount = 0x340c, BsmDramTextAddr = 0x3490, BsmDramTextSize = 0x3494, BsmDramDataAddr = 0x3498, BsmDramDataSize = 0x349c, BsmSramBase = 0x3800,}; enum { FilterPromisc = 1<<0, FilterCtl = 1<<1, FilterMulticast = 1<<2, FilterNoDecrypt = 1<<3, FilterBSS = 1<<5,}; enum { RFlag24Ghz = 1<<0, RFlagCCK = 1<<1, RFlagAuto = 1<<2, RFlagShSlot = 1<<4, RFlagShPreamble = 1<<5, RFlagNoDiversity = 1<<7, RFlagAntennaA = 1<<8, RFlagAntennaB = 1<<9, RFlagTSF = 1<<15,}; typedef struct FWSect FWSect;typedef struct FWImage FWImage; typedef struct TXQ TXQ;typedef struct RXQ RXQ; typedef struct Shared Shared;typedef struct Sample Sample;typedef struct Powergrp Powergrp; typedef struct Ctlr Ctlr; struct FWSect{ uchar *data; uint size;}; struct FWImage{ struct { FWSect text; FWSect data; } init, main, boot; uint version; uchar data[];}; struct TXQ{ uint n; uint i; Block **b; uchar *d; uchar *c; uint lastcmd; Rendez; QLock;}; struct RXQ{ uint i; Block **b; u32int *p;}; struct Shared{ u32int txbase[8]; u32int next; u32int reserved[2];}; struct Sample{ uchar index; char power;}; struct Powergrp{ uchar chan; char maxpwr; short temp; Sample samples[5];}; struct Ctlr { Lock; QLock; Ctlr *link; Pcidev *pdev; Wifi *wifi; int port; int power; int active; int broken; int attached; int temp; u32int ie; u32int *nic; /* assigned node ids in hardware node table or -1 if unassigned */ int bcastnodeid; int bssnodeid; /* current receiver settings */ uchar bssid[Eaddrlen]; int channel; int prom; int aid; RXQ rx; TXQ tx[8]; struct { Rendez; u32int m; u32int w; } wait; struct { uchar cap; u16int rev; uchar type; char regdom[4+1]; Powergrp pwrgrps[5]; } eeprom; char maxpwr[256]; Shared *shared; FWImage *fw;}; static void setled(Ctlr *ctlr, int which, int on, int off); #define csr32r(c, r) (*((c)->nic+((r)/4)))#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v)) static uintget32(uchar *p){ return *((u32int*)p);}static uintget16(uchar *p){ return *((u16int*)p);}static voidput32(uchar *p, uint v){ *((u32int*)p) = v;}static voidput16(uchar *p, uint v){ *((u16int*)p) = v;}; static char*niclock(Ctlr *ctlr){ int i; csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | MacAccessReq); for(i=0; i<1000; i++){ if((csr32r(ctlr, Gpc) & (NicSleep | MacAccessEna)) == MacAccessEna) return 0; delay(10); } return "niclock: timeout";} static voidnicunlock(Ctlr *ctlr){ csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) & ~MacAccessReq);} static u32intprphread(Ctlr *ctlr, uint off){ csr32w(ctlr, PrphRaddr, ((sizeof(u32int)-1)<<24) | off); coherence(); return csr32r(ctlr, PrphRdata);}static voidprphwrite(Ctlr *ctlr, uint off, u32int data){ csr32w(ctlr, PrphWaddr, ((sizeof(u32int)-1)<<24) | off); coherence(); csr32w(ctlr, PrphWdata, data);} static char*eepromread(Ctlr *ctlr, void *data, int count, uint off){ uchar *out = data; char *err; u32int w = 0; int i; if((err = niclock(ctlr)) != nil) return err; for(; count > 0; count -= 2, off++){ csr32w(ctlr, Eeprom, off << 2); csr32w(ctlr, Eeprom, csr32r(ctlr, Eeprom) & ~(1<<1)); for(i = 0; i < 10; i++){ w = csr32r(ctlr, Eeprom); if(w & 1) break; delay(5); } if(i == 10) break; *out++ = w >> 16; if(count > 1) *out++ = w >> 24; } nicunlock(ctlr); if(count > 0) return "eeprompread: timeout"; return nil;} static char*clockwait(Ctlr *ctlr){ int i; /* Set "initialization complete" bit. */ csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | InitDone); for(i=0; i<2500; i++){ if(csr32r(ctlr, Gpc) & MacClockReady) return nil; delay(10); } return "clockwait: timeout";} static char*poweron(Ctlr *ctlr){ char *err; if(ctlr->power) return nil; csr32w(ctlr, AnaPll, csr32r(ctlr, AnaPll) | Init); /* Disable L0s. */ csr32w(ctlr, GioChicken, csr32r(ctlr, GioChicken) | L1AnoL0Srx); if((err = clockwait(ctlr)) != nil) return err; if((err = niclock(ctlr)) != nil) return err; prphwrite(ctlr, ApmgClkEna, DmaClkRqt | BsmClkRqt); delay(20); /* Disable L1. */ prphwrite(ctlr, ApmgPciStt, prphread(ctlr, ApmgPciStt) | (1<<11)); nicunlock(ctlr); ctlr->power = 1; return nil;} static voidpoweroff(Ctlr *ctlr){ int i, j; csr32w(ctlr, Reset, Nevo); /* Disable interrupts. */ csr32w(ctlr, Imr, 0); csr32w(ctlr, Isr, ~0); csr32w(ctlr, FhIsr, ~0); if(niclock(ctlr) == nil){ /* Stop TX scheduler. */ prphwrite(ctlr, AlmSchedMode, 0); prphwrite(ctlr, AlmSchedTxfact, 0); /* Stop all DMA channels */ for(i = 0; i < 6; i++){ csr32w(ctlr, FhTxConfig + i*32, 0); for(j = 0; j < 100; j++){ if((csr32r(ctlr, FhTxStatus) & (0x1010000<<i)) == (0x1010000<<i)) break; delay(10); } } nicunlock(ctlr); } /* Stop RX ring. */ if(niclock(ctlr) == nil){ csr32w(ctlr, FhRxConfig, 0); for(j = 0; j < 100; j++){ if(csr32r(ctlr, FhRxStatus) & (1<<24)) break; delay(10); } nicunlock(ctlr); } if(niclock(ctlr) == nil){ prphwrite(ctlr, ApmgClkDis, DmaClkRqt); nicunlock(ctlr); } delay(5); csr32w(ctlr, Reset, csr32r(ctlr, Reset) | StopMaster); if((csr32r(ctlr, Gpc) & (7<<24)) != (4<<24)){ for(j = 0; j < 100; j++){ if(csr32r(ctlr, Reset) & MasterDisabled) break; delay(10); } } csr32w(ctlr, Reset, csr32r(ctlr, Reset) | SW); ctlr->power = 0;} static struct { u32int addr; /* offset in EEPROM */ u8int nchan; u8int chan[14];} bands[5] = { { 0x63, 14, { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 } }, { 0x72, 13, { 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 } }, { 0x80, 12, { 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 } }, { 0x8d, 11, { 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 } }, { 0x99, 6, { 145, 149, 153, 157, 161, 165 } }}; static intwpiinit(Ether *edev)Lines 1–500 of 1857. Load more
#include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "../port/error.h" #include "../port/netif.h" #include "etherif.h" #include "wifi.h" enum { Nrxlog = 6, Nrx = 1<<Nrxlog, Ntx = 256, Rbufsize = 3*1024, Rdscsize = 8, Tdscsize = 64, Tcmdsize = 128, }; /* registers */ enum { Cfg = 0x000, AlmMb = 1<<8, AlmMm = 1<<9, SkuMrc = 1<<10, RevD = 1<<11, TypeB = 1<<12, Isr = 0x008, Imr = 0x00c, Ialive = 1<<0, Iwakeup = 1<<1, Iswrx = 1<<3, Irftoggled = 1<<7, Iswerr = 1<<25, Ifhtx = 1<<27, Ihwerr = 1<<29, Ifhrx = 1<<31, Ierr = Iswerr | Ihwerr, Idefmask = Ierr | Ifhtx | Ifhrx | Ialive | Iwakeup | Iswrx | Irftoggled, FhIsr = 0x010, GpioIn = 0x018, Reset = 0x020, Nevo = 1<<0, SW = 1<<7, MasterDisabled = 1<<8, StopMaster = 1<<9, Gpc = 0x024, MacAccessEna = 1<<0, MacClockReady = 1<<0, InitDone = 1<<2, MacAccessReq = 1<<3, NicSleep = 1<<4, RfKill = 1<<27, Eeprom = 0x02c, EepromGp = 0x030, UcodeGp1Clr = 0x05c, UcodeGp1RfKill = 1<<1, UcodeGp1CmdBlocked = 1<<2, UcodeGp2 = 0x060, GioChicken = 0x100, L1AnoL0Srx = 1<<23, AnaPll = 0x20c, Init = 1<<24, PrphWaddr = 0x444, PrphRaddr = 0x448, PrphWdata = 0x44c, PrphRdata = 0x450, HbusTargWptr = 0x460, }; /* * Flow-Handler registers. */ enum { FhCbbcCtrl = 0x940, FhCbbcBase = 0x944, FhRxConfig = 0xc00, FhRxConfigDmaEna = 1<<31, FhRxConfigRdrbdEna = 1<<29, FhRxConfigWrstatusEna = 1<<27, FhRxConfigMaxfrag = 1<<24, FhRxConfigIrqDstHost = 1<<12, FhRxConfigNrdbShift = 20, FhRxConfigIrqRbthShift = 4, FhRxBase = 0xc04, FhRxWptr = 0xc20, FhRxRptrAddr = 0xc24, FhRssrTbl = 0xcc0, FhRxStatus = 0xcc4, FhTxConfig = 0xd00, // +q*32 FhTxBase = 0xe80, FhMsgConfig = 0xe88, FhTxStatus = 0xe90, }; /* * NIC internal memory offsets. */ enum { AlmSchedMode = 0x2e00, AlmSchedArastat = 0x2e04, AlmSchedTxfact = 0x2e10, AlmSchedTxf4mf = 0x2e14, AlmSchedTxf5mf = 0x2e20, AlmSchedBP1 = 0x2e2c, AlmSchedBP2 = 0x2e30, ApmgClkEna = 0x3004, ApmgClkDis = 0x3008, DmaClkRqt = 1<<9, BsmClkRqt = 1<<11, ApmgPs = 0x300c, PwrSrcVMain = 0<<24, PwrSrcMask = 3<<24, ApmgPciStt = 0x3010, BsmWrCtrl = 0x3400, BsmWrMemSrc = 0x3404, BsmWrMemDst = 0x3408, BsmWrDwCount = 0x340c, BsmDramTextAddr = 0x3490, BsmDramTextSize = 0x3494, BsmDramDataAddr = 0x3498, BsmDramDataSize = 0x349c, BsmSramBase = 0x3800, }; enum { FilterPromisc = 1<<0, FilterCtl = 1<<1, FilterMulticast = 1<<2, FilterNoDecrypt = 1<<3, FilterBSS = 1<<5, }; enum { RFlag24Ghz = 1<<0, RFlagCCK = 1<<1, RFlagAuto = 1<<2, RFlagShSlot = 1<<4, RFlagShPreamble = 1<<5, RFlagNoDiversity = 1<<7, RFlagAntennaA = 1<<8, RFlagAntennaB = 1<<9, RFlagTSF = 1<<15, }; typedef struct FWSect FWSect; typedef struct FWImage FWImage; typedef struct TXQ TXQ; typedef struct RXQ RXQ; typedef struct Shared Shared; typedef struct Sample Sample; typedef struct Powergrp Powergrp; typedef struct Ctlr Ctlr; struct FWSect { uchar *data; uint size; }; struct FWImage { struct { FWSect text; FWSect data; } init, main, boot; uint version; uchar data[]; }; struct TXQ { uint n; uint i; Block **b; uchar *d; uchar *c; uint lastcmd; Rendez; QLock; }; struct RXQ { uint i; Block **b; u32int *p; }; struct Shared { u32int txbase[8]; u32int next; u32int reserved[2]; }; struct Sample { uchar index; char power; }; struct Powergrp { uchar chan; char maxpwr; short temp; Sample samples[5]; }; struct Ctlr { Lock; QLock; Ctlr *link; Pcidev *pdev; Wifi *wifi; int port; int power; int active; int broken; int attached; int temp; u32int ie; u32int *nic; /* assigned node ids in hardware node table or -1 if unassigned */ int bcastnodeid; int bssnodeid; /* current receiver settings */ uchar bssid[Eaddrlen]; int channel; int prom; int aid; RXQ rx; TXQ tx[8]; struct { Rendez; u32int m; u32int w; } wait; struct { uchar cap; u16int rev; uchar type; char regdom[4+1]; Powergrp pwrgrps[5]; } eeprom; char maxpwr[256]; Shared *shared; FWImage *fw; }; static void setled(Ctlr *ctlr, int which, int on, int off); #define csr32r(c, r) (*((c)->nic+((r)/4))) #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v)) static uint get32(uchar *p){ return *((u32int*)p); } static uint get16(uchar *p) { return *((u16int*)p); } static void put32(uchar *p, uint v){ *((u32int*)p) = v; } static void put16(uchar *p, uint v){ *((u16int*)p) = v; }; static char* niclock(Ctlr *ctlr) { int i; csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | MacAccessReq); for(i=0; i<1000; i++){ if((csr32r(ctlr, Gpc) & (NicSleep | MacAccessEna)) == MacAccessEna) return 0; delay(10); } return "niclock: timeout"; } static void nicunlock(Ctlr *ctlr) { csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) & ~MacAccessReq); } static u32int prphread(Ctlr *ctlr, uint off) { csr32w(ctlr, PrphRaddr, ((sizeof(u32int)-1)<<24) | off); coherence(); return csr32r(ctlr, PrphRdata); } static void prphwrite(Ctlr *ctlr, uint off, u32int data) { csr32w(ctlr, PrphWaddr, ((sizeof(u32int)-1)<<24) | off); coherence(); csr32w(ctlr, PrphWdata, data); } static char* eepromread(Ctlr *ctlr, void *data, int count, uint off) { uchar *out = data; char *err; u32int w = 0; int i; if((err = niclock(ctlr)) != nil) return err; for(; count > 0; count -= 2, off++){ csr32w(ctlr, Eeprom, off << 2); csr32w(ctlr, Eeprom, csr32r(ctlr, Eeprom) & ~(1<<1)); for(i = 0; i < 10; i++){ w = csr32r(ctlr, Eeprom); if(w & 1) break; delay(5); } if(i == 10) break; *out++ = w >> 16; if(count > 1) *out++ = w >> 24; } nicunlock(ctlr); if(count > 0) return "eeprompread: timeout"; return nil; } static char* clockwait(Ctlr *ctlr) { int i; /* Set "initialization complete" bit. */ csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | InitDone); for(i=0; i<2500; i++){ if(csr32r(ctlr, Gpc) & MacClockReady) return nil; delay(10); } return "clockwait: timeout"; } static char* poweron(Ctlr *ctlr) { char *err; if(ctlr->power) return nil; csr32w(ctlr, AnaPll, csr32r(ctlr, AnaPll) | Init); /* Disable L0s. */ csr32w(ctlr, GioChicken, csr32r(ctlr, GioChicken) | L1AnoL0Srx); if((err = clockwait(ctlr)) != nil) return err; if((err = niclock(ctlr)) != nil) return err; prphwrite(ctlr, ApmgClkEna, DmaClkRqt | BsmClkRqt); delay(20); /* Disable L1. */ prphwrite(ctlr, ApmgPciStt, prphread(ctlr, ApmgPciStt) | (1<<11)); nicunlock(ctlr); ctlr->power = 1; return nil; } static void poweroff(Ctlr *ctlr) { int i, j; csr32w(ctlr, Reset, Nevo); /* Disable interrupts. */ csr32w(ctlr, Imr, 0); csr32w(ctlr, Isr, ~0); csr32w(ctlr, FhIsr, ~0); if(niclock(ctlr) == nil){ /* Stop TX scheduler. */ prphwrite(ctlr, AlmSchedMode, 0); prphwrite(ctlr, AlmSchedTxfact, 0); /* Stop all DMA channels */ for(i = 0; i < 6; i++){ csr32w(ctlr, FhTxConfig + i*32, 0); for(j = 0; j < 100; j++){ if((csr32r(ctlr, FhTxStatus) & (0x1010000<<i)) == (0x1010000<<i)) break; delay(10); } } nicunlock(ctlr); } /* Stop RX ring. */ if(niclock(ctlr) == nil){ csr32w(ctlr, FhRxConfig, 0); for(j = 0; j < 100; j++){ if(csr32r(ctlr, FhRxStatus) & (1<<24)) break; delay(10); } nicunlock(ctlr); } if(niclock(ctlr) == nil){ prphwrite(ctlr, ApmgClkDis, DmaClkRqt); nicunlock(ctlr); } delay(5); csr32w(ctlr, Reset, csr32r(ctlr, Reset) | StopMaster); if((csr32r(ctlr, Gpc) & (7<<24)) != (4<<24)){ for(j = 0; j < 100; j++){ if(csr32r(ctlr, Reset) & MasterDisabled) break; delay(10); } } csr32w(ctlr, Reset, csr32r(ctlr, Reset) | SW); ctlr->power = 0; } static struct { u32int addr; /* offset in EEPROM */ u8int nchan; u8int chan[14]; } bands[5] = { { 0x63, 14, { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 } }, { 0x72, 13, { 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 } }, { 0x80, 12, { 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 } }, { 0x8d, 11, { 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 } }, { 0x99, 6, { 145, 149, 153, 157, 161, 165 } } }; static int wpiinit(Ether *edev)