etherbcm.c.NO 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. /*
  10. * Broadcom BCM57xx
  11. * Not implemented:
  12. * proper fatal error handling
  13. * multiple rings
  14. * checksum offloading
  15. */
  16. #include "u.h"
  17. #include "../port/lib.h"
  18. #include "mem.h"
  19. #include "dat.h"
  20. #include "fns.h"
  21. #include "io.h"
  22. #include "../port/error.h"
  23. #include "../port/netif.h"
  24. #include "etherif.h"
  25. #include "../port/ethermii.h"
  26. #define dprint(...) do{ if(debug)print(__VA_ARGS__); }while(0)
  27. #define Rbsz ROUNDUP(sizeof(Etherpkt)+4, 4)
  28. typedef struct Ctlr Ctlr;
  29. struct Ctlr {
  30. Lock txlock, imlock;
  31. Ether *ether;
  32. Ctlr *next;
  33. Pcidev *pdev;
  34. uint32_t *nic, *status;
  35. uint32_t *recvret, *recvprod, *sendr;
  36. uint32_t port;
  37. uint recvreti, recvprodi, sendri, sendcleani;
  38. Block **sends;
  39. Block **rxs;
  40. int active, duplex;
  41. int type;
  42. uint nobuf;
  43. uint partial;
  44. uint rxerr;
  45. uint qfull;
  46. uint dmaerr;
  47. };
  48. enum {
  49. /* configurable constants */
  50. RxRetRingLen = 0x200,
  51. RxProdRingLen = 0x200,
  52. SendRingLen = 0x200,
  53. Reset = 1<<0,
  54. Enable = 1<<1,
  55. Attn = 1<<2,
  56. Pwrctlstat = 0x4C,
  57. MiscHostCtl = 0x68,
  58. TaggedStatus = 1<<9,
  59. IndirAccessEn = 1<<7,
  60. EnableClockCtl = 1<<5,
  61. PCIStateRegEn = 1<<4,
  62. WordSwap = 1<<3,
  63. ByteSwap = 1<<2,
  64. MaskPCIInt = 1<<1,
  65. ClearIntA = 1<<0,
  66. Fwmbox = 0x0b50, /* magic value exchange */
  67. Fwmagic = 0x4b657654,
  68. Dmarwctl = 0x6C,
  69. DMAWaterMask = ~(7<<19),
  70. DMAWaterValue = 3<<19,
  71. Memwind = 0x7C,
  72. MemwindData = 0x84,
  73. SendRCB = 0x100,
  74. RxRetRCB = 0x200,
  75. InterruptMailbox = 0x204,
  76. RxProdBDRingIdx = 0x26c,
  77. RxBDRetRingIdx = 0x284,
  78. SendBDRingHostIdx = 0x304,
  79. MACMode = 0x400,
  80. MACPortMask = ~(1<<3 | 1<<2),
  81. MACPortGMII = 1<<3,
  82. MACPortMII = 1<<2,
  83. MACEnable = 1<<23 | 1<<22 | 1<<21 | 1 << 15 | 1 << 14 | 1<<12 | 1<<11,
  84. MACHalfDuplex = 1<<1,
  85. MACEventStatus = 0x404,
  86. MACEventEnable = 0x408,
  87. MACAddress = 0x410,
  88. RandomBackoff = 0x438,
  89. RxMTU = 0x43C,
  90. MIComm = 0x44C,
  91. MIStatus = 0x450,
  92. MIMode = 0x454,
  93. RxMACMode = 0x468,
  94. TxMACMode = 0x45C,
  95. TxMACLengths = 0x464,
  96. MACHash = 0x470,
  97. RxRules = 0x480,
  98. RxRulesConf = 0x500,
  99. LowWaterMax = 0x504,
  100. LowWaterMaxMask = ~0xFFFF,
  101. LowWaterMaxValue = 2,
  102. SendDataInitiatorMode = 0xC00,
  103. SendInitiatorConf = 0x0C08,
  104. SendStats = 1<<0,
  105. SendInitiatorMask = 0x0C0C,
  106. SendDataCompletionMode = 0x1000,
  107. SendBDSelectorMode = 0x1400,
  108. SendBDInitiatorMode = 0x1800,
  109. SendBDCompletionMode = 0x1C00,
  110. RxListPlacementMode = 0x2000,
  111. RxListPlacement = 0x2010,
  112. RxListPlacementConf = 0x2014,
  113. RxStats = 1<<0,
  114. RxListPlacementMask = 0x2018,
  115. RxDataBDInitiatorMode = 0x2400,
  116. RxBDHostAddr = 0x2450,
  117. RxBDFlags = 0x2458,
  118. RxBDNIC = 0x245C,
  119. RxDataCompletionMode = 0x2800,
  120. RxBDInitiatorMode = 0x2C00,
  121. RxBDRepl = 0x2C18,
  122. RxBDCompletionMode = 0x3000,
  123. HostCoalMode = 0x3C00,
  124. HostCoalRxTicks = 0x3C08,
  125. HostCoalSendTicks = 0x3C0C,
  126. RxMaxCoalFrames = 0x3C10,
  127. SendMaxCoalFrames = 0x3C14,
  128. RxMaxCoalFramesInt = 0x3C20,
  129. SendMaxCoalFramesInt = 0x3C24,
  130. StatusBlockHostAddr = 0x3C38,
  131. FlowAttention = 0x3C48,
  132. MemArbiterMode = 0x4000,
  133. BufferManMode = 0x4400,
  134. MBUFLowWater = 0x4414,
  135. MBUFHighWater = 0x4418,
  136. ReadDMAMode = 0x4800,
  137. ReadDMAStatus = 0x4804,
  138. WriteDMAMode = 0x4C00,
  139. WriteDMAStatus = 0x4C04,
  140. RISCState = 0x5004,
  141. FTQReset = 0x5C00,
  142. MSIMode = 0x6000,
  143. ModeControl = 0x6800,
  144. ByteWordSwap = 1<<4 | 1<<5 | 1<<2, // | 1<<1,
  145. HostStackUp = 1<<16,
  146. HostSendBDs = 1<<17,
  147. InterruptOnMAC = 1<<26,
  148. MiscConf = 0x6804,
  149. CoreClockBlocksReset = 1<<0,
  150. GPHYPwrdnOverride = 1<<26,
  151. DisableGRCRstOnPpcie = 1<<29,
  152. TimerMask = ~0xFF,
  153. TimerValue = 65<<1,
  154. MiscLocalControl = 0x6808,
  155. InterruptOnAttn = 1<<3,
  156. AutoSEEPROM = 1<<24,
  157. SwArbitration = 0x7020,
  158. SwArbitSet1 = 1<<1,
  159. SwArbitWon1 = 1<<9,
  160. Pcitlplpl = 0x7C00, /* "lower 1k of the pcie pl regs" ?? */
  161. PhyAuxControl = 0x18,
  162. PhyIntStatus = 0x1A,
  163. PhyIntMask = 0x1B,
  164. Updated = 1<<0,
  165. LinkStateChange = 1<<1,
  166. Error = 1<<2,
  167. PacketEnd = 1<<2,
  168. FrameError = 1<<10,
  169. };
  170. enum {
  171. b5722,
  172. b5751,
  173. b5754,
  174. b5755,
  175. b5756,
  176. b5782,
  177. b5787,
  178. b5906,
  179. Nctlrtype,
  180. };
  181. typedef struct Ctlrtype Ctlrtype;
  182. struct Ctlrtype {
  183. int mtu;
  184. int flag;
  185. char *name;
  186. };
  187. static Ctlrtype cttab[Nctlrtype] = {
  188. [b5722] 1514, 0, "b5722",
  189. [b5751] 1514, 0, "b5751",
  190. [b5754] 1514, 0, "b5754",
  191. [b5755] 1514, 0, "b5755",
  192. [b5756] 1514, 0, "b5756",
  193. [b5782] 1514, 0, "b5782",
  194. [b5787] 1514, 0, "b5787",
  195. [b5906] 1514, 0, "b5906",
  196. };
  197. #define csr32(c, r) ((c)->nic[(r)/4])
  198. static Ctlr *bcmhead;
  199. static int debug=1;
  200. static char*
  201. cname(Ctlr *c)
  202. {
  203. return cttab[c->type].name;
  204. }
  205. static int32_t
  206. bcmifstat(Ether *edev, void *a, int32_t n, uint32_t offset)
  207. {
  208. char *s, *p, *e;
  209. Ctlr *c;
  210. c = edev->ctlr;
  211. p = s = malloc(READSTR);
  212. e = p + READSTR;
  213. p = seprint(p, e, "nobuf %ud\n", c->nobuf);
  214. p = seprint(p, e, "partial %ud\n", c->partial);
  215. p = seprint(p, e, "rxerr %ud\n", c->rxerr);
  216. p = seprint(p, e, "qfull %ud\n", c->qfull);
  217. p = seprint(p, e, "dmaerr %ud\n", c->dmaerr);
  218. p = seprint(p, e, "type: %s\n", cname(c));
  219. USED(p);
  220. n = readstr(offset, a, n, s);
  221. free(s);
  222. return n;
  223. }
  224. enum {
  225. Phybusy = 1<<29,
  226. Phyrdfail = 1<<28,
  227. Phyrd = 1<<27,
  228. Phywr = 1<<26,
  229. };
  230. Lock miilock;
  231. static uint
  232. miiwait(Ctlr *ctlr)
  233. {
  234. uint i, v;
  235. for(i = 0; i < 100; i += 5){
  236. microdelay(10);
  237. v = csr32(ctlr, MIComm);
  238. if((v & Phybusy) == 0){
  239. microdelay(5);
  240. return csr32(ctlr, MIComm);
  241. }
  242. microdelay(5);
  243. }
  244. print("#l%d: bcm: miiwait: timeout\n", ctlr->ether->ctlrno);
  245. return ~0;
  246. }
  247. static int
  248. miir(Ctlr *ctlr, int r)
  249. {
  250. uint v, phyno;
  251. phyno = 1;
  252. lock(&miilock);
  253. csr32(ctlr, MIComm) = r<<16 | phyno<<21 | Phyrd | Phybusy;
  254. v = miiwait(ctlr);
  255. unlock(&miilock);
  256. if(v == ~0)
  257. return -1;
  258. if(v & Phyrdfail){
  259. print("#l%d: bcm: miir: fail\n", ctlr->ether->ctlrno);
  260. return -1;
  261. }
  262. return v & 0xffff;
  263. }
  264. static int
  265. miiw(Ctlr *ctlr, int r, int v)
  266. {
  267. uint phyno, w;
  268. phyno = 1;
  269. lock(&miilock);
  270. csr32(ctlr, MIComm) = r<<16 | v&0xffff | phyno<<21 | Phywr | Phybusy;
  271. w = miiwait(ctlr);
  272. unlock(&miilock);
  273. if(w == ~0)
  274. return -1;
  275. return 0;
  276. }
  277. static void
  278. checklink(Ether *edev)
  279. {
  280. uint i;
  281. Ctlr *ctlr;
  282. ctlr = edev->ctlr;
  283. miir(ctlr, Bmsr); /* read twice for current status as per 802.3 */
  284. if(!(miir(ctlr, Bmsr) & BmsrLs)) {
  285. edev->link = 0;
  286. edev->mbps = 1000;
  287. ctlr->duplex = 1;
  288. dprint("bcm: no link\n");
  289. goto out;
  290. }
  291. edev->link = 1;
  292. while((miir(ctlr, Bmsr) & BmsrAnc) == 0)
  293. ;
  294. i = miir(ctlr, Mssr);
  295. if(i & (Mssr1000THD | Mssr1000TFD)) {
  296. edev->mbps = 1000;
  297. ctlr->duplex = (i & Mssr1000TFD) != 0;
  298. } else if(i = miir(ctlr, Anlpar), i & (AnaTXHD | AnaTXFD)) {
  299. edev->mbps = 100;
  300. ctlr->duplex = (i & AnaTXFD) != 0;
  301. } else if(i & (Ana10HD | Ana10FD)) {
  302. edev->mbps = 10;
  303. ctlr->duplex = (i & Ana10FD) != 0;
  304. } else {
  305. edev->link = 0;
  306. edev->mbps = 1000;
  307. ctlr->duplex = 1;
  308. dprint("bcm: link partner supports neither 10/100/1000 Mbps\n");
  309. goto out;
  310. }
  311. dprint("bcm: %d Mbps link, %s duplex\n", edev->mbps, ctlr->duplex ? "full" : "half");
  312. out:
  313. if(ctlr->duplex)
  314. csr32(ctlr, MACMode) &= ~MACHalfDuplex;
  315. else
  316. csr32(ctlr, MACMode) |= MACHalfDuplex;
  317. if(edev->mbps >= 1000)
  318. csr32(ctlr, MACMode) = (csr32(ctlr, MACMode) & MACPortMask) | MACPortGMII;
  319. else
  320. csr32(ctlr, MACMode) = (csr32(ctlr, MACMode) & MACPortMask) | MACPortMII;
  321. csr32(ctlr, MACEventStatus) |= (1<<4) | (1<<3); /* undocumented bits (sync and config changed) */
  322. }
  323. static uint*
  324. currentrecvret(Ctlr *ctlr)
  325. {
  326. if(ctlr->recvreti == (ctlr->status[4] & 0xFFFF))
  327. return 0;
  328. return ctlr->recvret + ctlr->recvreti * 8;
  329. }
  330. static void
  331. consumerecvret(Ctlr *ctlr)
  332. {
  333. ctlr->recvreti = ctlr->recvreti+1 & RxRetRingLen-1;
  334. csr32(ctlr, RxBDRetRingIdx) = ctlr->recvreti;
  335. }
  336. static int
  337. replenish(Ctlr *ctlr)
  338. {
  339. uint incr;
  340. uint32_t *next;
  341. Block *bp;
  342. incr = (ctlr->recvprodi + 1) & (RxProdRingLen - 1);
  343. if(incr == (ctlr->status[2] >> 16))
  344. return -1;
  345. bp = iallocb(Rbsz);
  346. if(bp == nil) {
  347. /* iallocb never fails. this code is unnecessary */
  348. dprint("bcm: out of memory for receive buffers\n");
  349. ctlr->nobuf++;
  350. return -1;
  351. }
  352. next = ctlr->recvprod + ctlr->recvprodi * 8;
  353. memset(next, 0, 32);
  354. next[0] = Pciwaddrh(bp->rp);
  355. next[1] = Pciwaddrl(bp->rp);
  356. next[2] = Rbsz;
  357. next[7] = ctlr->recvprodi;
  358. ctlr->rxs[ctlr->recvprodi] = bp;
  359. coherence();
  360. csr32(ctlr, RxProdBDRingIdx) = ctlr->recvprodi = incr;
  361. return 0;
  362. }
  363. static void
  364. bcmreceive(Ether *edev)
  365. {
  366. uint len;
  367. uint32_t *pkt;
  368. Ctlr *ctlr;
  369. Block *bp;
  370. ctlr = edev->ctlr;
  371. for(; pkt = currentrecvret(ctlr); replenish(ctlr), consumerecvret(ctlr)) {
  372. bp = ctlr->rxs[pkt[7]];
  373. len = pkt[2] & 0xFFFF;
  374. bp->wp = bp->rp + len;
  375. if((pkt[3] & PacketEnd) == 0){
  376. dprint("bcm: partial frame received -- shouldn't happen\n");
  377. ctlr->partial++;
  378. freeb(bp);
  379. continue;
  380. }
  381. if(pkt[3] & FrameError){
  382. ctlr->rxerr++;
  383. freeb(bp);
  384. continue;
  385. }
  386. etheriq(edev, bp, 1);
  387. }
  388. }
  389. static void
  390. bcmtransclean(Ether *edev)
  391. {
  392. Ctlr *ctlr;
  393. ctlr = edev->ctlr;
  394. ilock(&ctlr->txlock);
  395. while(ctlr->sendcleani != (ctlr->status[4] >> 16)) {
  396. freeb(ctlr->sends[ctlr->sendcleani]);
  397. ctlr->sends[ctlr->sendcleani] = nil;
  398. ctlr->sendcleani = (ctlr->sendcleani + 1) & (SendRingLen - 1);
  399. }
  400. iunlock(&ctlr->txlock);
  401. }
  402. static void
  403. bcmtransmit(Ether *edev)
  404. {
  405. uint incr;
  406. uint32_t *next;
  407. Ctlr *ctlr;
  408. Block *bp;
  409. ctlr = edev->ctlr;
  410. ilock(&ctlr->txlock);
  411. for(;;){
  412. incr = (ctlr->sendri + 1) & (SendRingLen - 1);
  413. if(incr == ctlr->sendcleani) {
  414. dprint("bcm: send queue full\n");
  415. ctlr->qfull++;
  416. break;
  417. }
  418. bp = qget(edev->oq);
  419. if(bp == nil)
  420. break;
  421. next = ctlr->sendr + ctlr->sendri * 4;
  422. next[0] = Pciwaddrh(bp->rp);
  423. next[1] = Pciwaddrl(bp->rp);
  424. next[2] = (BLEN(bp) << 16) | PacketEnd;
  425. next[3] = 0;
  426. ctlr->sends[ctlr->sendri] = bp;
  427. coherence();
  428. csr32(ctlr, SendBDRingHostIdx) = ctlr->sendri = incr;
  429. }
  430. iunlock(&ctlr->txlock);
  431. }
  432. static void
  433. bcmerror(Ether *edev)
  434. {
  435. Ctlr *ctlr;
  436. ctlr = edev->ctlr;
  437. if(csr32(ctlr, FlowAttention)) {
  438. if(csr32(ctlr, FlowAttention) & 0xf8ff8080)
  439. print("bcm: fatal error %#.8ux", csr32(ctlr, FlowAttention));
  440. csr32(ctlr, FlowAttention) = 0;
  441. }
  442. csr32(ctlr, MACEventStatus) = 0; /* worth ignoring */
  443. if(csr32(ctlr, ReadDMAStatus) || csr32(ctlr, WriteDMAStatus)) {
  444. dprint("bcm: DMA error\n");
  445. ctlr->dmaerr++;
  446. csr32(ctlr, ReadDMAStatus) = 0;
  447. csr32(ctlr, WriteDMAStatus) = 0;
  448. }
  449. if(csr32(ctlr, RISCState)) {
  450. if(csr32(ctlr, RISCState) & 0x78000403)
  451. print("bcm: RISC halted %#.8ux", csr32(ctlr, RISCState));
  452. csr32(ctlr, RISCState) = 0;
  453. }
  454. }
  455. static void
  456. bcminterrupt(Ureg*u, void *arg)
  457. {
  458. uint32_t status, tag, dummy;
  459. Ether *edev;
  460. Ctlr *ctlr;
  461. edev = arg;
  462. ctlr = edev->ctlr;
  463. ilock(&ctlr->imlock);
  464. dummy = csr32(ctlr, InterruptMailbox);
  465. USED(dummy);
  466. csr32(ctlr, InterruptMailbox) = 1;
  467. status = ctlr->status[0];
  468. tag = ctlr->status[1];
  469. ctlr->status[0] = 0;
  470. if(status & Error)
  471. bcmerror(edev);
  472. if(status & LinkStateChange)
  473. checklink(edev);
  474. if(0)
  475. iprint("bcm: interrupt %.8ux %.8ux\n", ctlr->status[2], ctlr->status[4]);
  476. bcmreceive(edev);
  477. bcmtransclean(edev);
  478. bcmtransmit(edev);
  479. csr32(ctlr, InterruptMailbox) = tag << 24;
  480. iunlock(&ctlr->imlock);
  481. }
  482. static void
  483. mem32w(Ctlr *c, uint r, uint v)
  484. {
  485. pcicfgw32(c->pdev, Memwind, r);
  486. pcicfgw32(c->pdev, MemwindData, v);
  487. }
  488. static uint32_t
  489. mem32r(Ctlr *c, uint r)
  490. {
  491. uint32_t v;
  492. pcicfgw32(c->pdev, Memwind, r);
  493. v = pcicfgr32(c->pdev, MemwindData);
  494. pcicfgw32(c->pdev, Memwind, 0);
  495. return v;
  496. }
  497. static int
  498. bcmmicrowait(Ctlr *ctlr, uint to, uint r, uint m, uint v)
  499. {
  500. int i;
  501. for(i = 0;; i += 100){
  502. if((csr32(ctlr, r) & m) == v)
  503. return 0;
  504. if(i == to /* µs */)
  505. return -1;
  506. microdelay(100);
  507. }
  508. }
  509. static int
  510. bcminit(Ether *edev)
  511. {
  512. uint i;
  513. uint32_t j;
  514. Ctlr *ctlr;
  515. ctlr = edev->ctlr;
  516. dprint("bcm: reset\n");
  517. /* initialization procedure according to the datasheet */
  518. csr32(ctlr, MiscHostCtl) |= MaskPCIInt | ClearIntA | WordSwap | IndirAccessEn;
  519. csr32(ctlr, SwArbitration) |= SwArbitSet1;
  520. if(bcmmicrowait(ctlr, 2000, SwArbitration, SwArbitWon1, SwArbitWon1) == -1){
  521. print("bcm: arbiter failed to respond\n");
  522. return -1;
  523. }
  524. csr32(ctlr, MemArbiterMode) |= Enable;
  525. csr32(ctlr, MiscHostCtl) = WordSwap | IndirAccessEn | PCIStateRegEn | EnableClockCtl
  526. | MaskPCIInt | ClearIntA;
  527. csr32(ctlr, Memwind) = 0;
  528. mem32w(ctlr, Fwmbox, Fwmagic);
  529. csr32(ctlr, MiscConf) |= GPHYPwrdnOverride | DisableGRCRstOnPpcie | CoreClockBlocksReset;
  530. delay(100);
  531. pcicfgw32(ctlr->pdev, PciPCR, ctlr->pdev->pcr); /* restore pci bits lost */
  532. csr32(ctlr, MiscHostCtl) |= MaskPCIInt | ClearIntA;
  533. csr32(ctlr, MemArbiterMode) |= Enable;
  534. csr32(ctlr, MiscHostCtl) |= WordSwap | IndirAccessEn | PCIStateRegEn | EnableClockCtl | TaggedStatus;
  535. csr32(ctlr, ModeControl) |= ByteWordSwap;
  536. csr32(ctlr, MACMode) = (csr32(ctlr, MACMode) & MACPortMask) | MACPortGMII;
  537. delay(40);
  538. for(i = 0;; i += 100){
  539. if(mem32r(ctlr, Fwmbox) == ~Fwmagic)
  540. break;
  541. if(i == 20*10000 /* micros */){
  542. print("bcm: fw failed to respond %#.8ux\n", mem32r(ctlr, Fwmbox));
  543. break; //return -1;
  544. }
  545. microdelay(100);
  546. }
  547. /*
  548. * there appears to be no justification for setting these bits in any driver
  549. * i can find. nor to i have a datasheet that recommends this. - quanstro
  550. * csr32(ctlr, Pcitlplpl) |= 1<<25 | 1<<29;
  551. */
  552. memset(ctlr->status, 0, 20);
  553. csr32(ctlr, Dmarwctl) = (csr32(ctlr, Dmarwctl) & DMAWaterMask) | DMAWaterValue;
  554. csr32(ctlr, ModeControl) |= HostSendBDs | HostStackUp | InterruptOnMAC;
  555. csr32(ctlr, MiscConf) = (csr32(ctlr, MiscConf) & TimerMask) | TimerValue;
  556. csr32(ctlr, MBUFLowWater) = 0x20;
  557. csr32(ctlr, MBUFHighWater) = 0x60;
  558. csr32(ctlr, LowWaterMax) = (csr32(ctlr, LowWaterMax) & LowWaterMaxMask) | LowWaterMaxValue;
  559. csr32(ctlr, BufferManMode) |= Enable | Attn;
  560. if(bcmmicrowait(ctlr, 2000, BufferManMode, Enable, Enable) == -1){
  561. print("bcm: failed to enable buffers\n");
  562. return -1;
  563. }
  564. csr32(ctlr, FTQReset) = ~0;
  565. csr32(ctlr, FTQReset) = 0;
  566. if(bcmmicrowait(ctlr, 2000, FTQReset, ~0, 0) == -1){
  567. print("bcm: failed to bring ftq out of reset\n");
  568. return -1;
  569. }
  570. csr32(ctlr, RxBDHostAddr) = Pciwaddrh(ctlr->recvprod);
  571. csr32(ctlr, RxBDHostAddr + 4) = Pciwaddrl(ctlr->recvprod);
  572. csr32(ctlr, RxBDFlags) = RxProdRingLen << 16;
  573. csr32(ctlr, RxBDNIC) = 0x6000;
  574. csr32(ctlr, RxBDRepl) = 25;
  575. csr32(ctlr, SendBDRingHostIdx) = 0;
  576. csr32(ctlr, SendBDRingHostIdx+4) = 0;
  577. mem32w(ctlr, SendRCB, Pciwaddrh(ctlr->sendr));
  578. mem32w(ctlr, SendRCB + 4, Pciwaddrl(ctlr->sendr));
  579. mem32w(ctlr, SendRCB + 8, SendRingLen << 16);
  580. mem32w(ctlr, SendRCB + 12, 0x4000);
  581. for(i=1; i<4; i++)
  582. mem32w(ctlr, RxRetRCB + i * 0x10 + 8, 2);
  583. mem32w(ctlr, RxRetRCB, Pciwaddrh(ctlr->recvret));
  584. mem32w(ctlr, RxRetRCB + 4, Pciwaddrl(ctlr->recvret));
  585. mem32w(ctlr, RxRetRCB + 8, RxRetRingLen << 16);
  586. csr32(ctlr, RxProdBDRingIdx) = 0;
  587. csr32(ctlr, RxProdBDRingIdx+4) = 0;
  588. /* this delay is not in the datasheet, but necessary */
  589. delay(1);
  590. i = csr32(ctlr, MACAddress);
  591. j = edev->ea[0] = i >> 8;
  592. j += edev->ea[1] = i;
  593. i = csr32(ctlr, MACAddress + 4);
  594. j += edev->ea[2] = i >> 24;
  595. j += edev->ea[3] = i >> 16;
  596. j += edev->ea[4] = i >> 8;
  597. j += edev->ea[5] = i;
  598. csr32(ctlr, RandomBackoff) = j & 0x3FF;
  599. csr32(ctlr, RxMTU) = Rbsz;
  600. csr32(ctlr, TxMACLengths) = 0x2620;
  601. csr32(ctlr, RxListPlacement) = 1<<3; /* one list */
  602. csr32(ctlr, RxListPlacementMask) = 0xFFFFFF;
  603. csr32(ctlr, RxListPlacementConf) |= RxStats;
  604. csr32(ctlr, SendInitiatorMask) = 0xFFFFFF;
  605. csr32(ctlr, SendInitiatorConf) |= SendStats;
  606. csr32(ctlr, HostCoalMode) = 0;
  607. if(bcmmicrowait(ctlr, 2000, HostCoalMode, ~0, 0) == -1){
  608. print("bcm: failed to unset coalescing\n");
  609. return -1;
  610. }
  611. csr32(ctlr, HostCoalRxTicks) = 150;
  612. csr32(ctlr, HostCoalSendTicks) = 150;
  613. csr32(ctlr, RxMaxCoalFrames) = 10;
  614. csr32(ctlr, SendMaxCoalFrames) = 10;
  615. csr32(ctlr, RxMaxCoalFramesInt) = 0;
  616. csr32(ctlr, SendMaxCoalFramesInt) = 0;
  617. csr32(ctlr, StatusBlockHostAddr) = Pciwaddrh(ctlr->status);
  618. csr32(ctlr, StatusBlockHostAddr + 4) = Pciwaddrl(ctlr->status);
  619. csr32(ctlr, HostCoalMode) |= Enable;
  620. csr32(ctlr, RxBDCompletionMode) |= Enable | Attn;
  621. csr32(ctlr, RxListPlacementMode) |= Enable;
  622. csr32(ctlr, MACMode) |= MACEnable;
  623. csr32(ctlr, MiscLocalControl) |= InterruptOnAttn | AutoSEEPROM;
  624. csr32(ctlr, InterruptMailbox) = 0;
  625. csr32(ctlr, WriteDMAMode) |= 0x200003fe; /* pulled out of my nose */
  626. csr32(ctlr, ReadDMAMode) |= 0x3fe;
  627. csr32(ctlr, RxDataCompletionMode) |= Enable | Attn;
  628. csr32(ctlr, SendDataCompletionMode) |= Enable;
  629. csr32(ctlr, SendBDCompletionMode) |= Enable | Attn;
  630. csr32(ctlr, RxBDInitiatorMode) |= Enable | Attn;
  631. csr32(ctlr, RxDataBDInitiatorMode) |= Enable | (1<<4);
  632. csr32(ctlr, SendDataInitiatorMode) |= Enable;
  633. csr32(ctlr, SendBDInitiatorMode) |= Enable | Attn;
  634. csr32(ctlr, SendBDSelectorMode) |= Enable | Attn;
  635. ctlr->recvprodi = 0;
  636. while(replenish(ctlr) >= 0)
  637. ;
  638. csr32(ctlr, TxMACMode) |= Enable;
  639. csr32(ctlr, RxMACMode) |= Enable;
  640. csr32(ctlr, Pwrctlstat) &= ~3;
  641. csr32(ctlr, MIStatus) |= 1<<0;
  642. csr32(ctlr, MACEventEnable) = 0;
  643. csr32(ctlr, MACEventStatus) |= (1<<12);
  644. csr32(ctlr, MIMode) = 0xC0000; /* set base mii clock */
  645. microdelay(40);
  646. if(0){
  647. /* bug (ours): can't reset phy without dropping into 100mbit mode */
  648. miiw(ctlr, Bmcr, BmcrR);
  649. for(i = 0;; i += 100){
  650. if((miir(ctlr, Bmcr) & BmcrR) == 0)
  651. break;
  652. if(i == 10000 /* micros */){
  653. print("bcm: phy reset failure\n");
  654. return -1;
  655. }
  656. microdelay(100);
  657. }
  658. }
  659. miiw(ctlr, Bmcr, BmcrAne | BmcrRan);
  660. miiw(ctlr, PhyAuxControl, 2);
  661. miir(ctlr, PhyIntStatus);
  662. miir(ctlr, PhyIntStatus);
  663. miiw(ctlr, PhyIntMask, ~(1<<1));
  664. csr32(ctlr, MACEventEnable) |= 1<<12;
  665. for(i = 0; i < 4; i++)
  666. csr32(ctlr, MACHash + 4*i) = ~0;
  667. for(i = 0; i < 8; i++)
  668. csr32(ctlr, RxRules + 8 * i) = 0;
  669. csr32(ctlr, RxRulesConf) = 1 << 3;
  670. csr32(ctlr, MSIMode) |= Enable;
  671. csr32(ctlr, MiscHostCtl) &= ~(MaskPCIInt | ClearIntA);
  672. dprint("bcm: reset: fin\n");
  673. return 0;
  674. }
  675. static int
  676. didtype(Pcidev *p)
  677. {
  678. if(p->vid != 0x14e4)
  679. return -1;
  680. switch(p->did){
  681. default:
  682. return -1;
  683. case 0x165a: /* 5722 gbe */
  684. return b5722;
  685. case 0x1670: /* ?? */
  686. return b5751;
  687. case 0x1672: /* 5754m */
  688. return b5754;
  689. case 0x1673: /* 5755m gbe */
  690. return b5755;
  691. case 0x1674: /* 5756me gbe */
  692. return b5756;
  693. case 0x1677: /* 5751 gbe */
  694. return b5751;
  695. case 0x167a: /* 5754 gbe */
  696. return b5754;
  697. case 0x167b: /* 5755 gbe */
  698. return b5755;
  699. case 0x1693: /* 5787m gbe */
  700. return b5787;
  701. case 0x1696: /* 5782 gbe; steve */
  702. return b5782;
  703. case 0x169b: /* 5787 gbe */
  704. return b5787;
  705. case 0x1712: /* 5906 fast */
  706. case 0x1713: /* 5906m fast */
  707. return b5906;
  708. case 0x167d: /* 5751m gbe */
  709. case 0x167e: /* 5751f fast */
  710. return b5751;
  711. }
  712. }
  713. static void
  714. bcmpci(void)
  715. {
  716. int type;
  717. void *mem;
  718. Ctlr *ctlr, **xx;
  719. Pcidev *p;
  720. xx = &bcmhead;
  721. for(p = nil; p = pcimatch(p, 0, 0); ) {
  722. if(p->ccrb != 2 || p->ccru != 0 || (type = didtype(p)) == -1)
  723. continue;
  724. pcisetbme(p);
  725. pcisetpms(p, 0);
  726. ctlr = malloc(sizeof(Ctlr));
  727. if(ctlr == nil)
  728. continue;
  729. ctlr->type = type;
  730. ctlr->port = p->mem[0].bar & ~0x0F;
  731. mem = vmap(ctlr->port, p->mem[0].size);
  732. if(mem == nil) {
  733. print("bcm: can't map %#p\n", (uint64_t)ctlr->port);
  734. free(ctlr);
  735. continue;
  736. }
  737. ctlr->pdev = p;
  738. ctlr->nic = mem;
  739. ctlr->status = mallocalign(20, 16, 0, 0);
  740. ctlr->recvprod = mallocalign(32 * RxProdRingLen, 16, 0, 0);
  741. ctlr->recvret = mallocalign(32 * RxRetRingLen, 16, 0, 0);
  742. ctlr->sendr = mallocalign(16 * SendRingLen, 16, 0, 0);
  743. ctlr->sends = malloc(sizeof *ctlr->sends * SendRingLen);
  744. ctlr->rxs = malloc(sizeof *ctlr->sends * SendRingLen);
  745. *xx = ctlr;
  746. xx = &ctlr->next;
  747. }
  748. }
  749. static void
  750. bcmpromiscuous(void* arg, int on)
  751. {
  752. Ctlr *ctlr;
  753. ctlr = ((Ether*)arg)->ctlr;
  754. if(on)
  755. csr32(ctlr, RxMACMode) |= 1<<8;
  756. else
  757. csr32(ctlr, RxMACMode) &= ~(1<<8);
  758. }
  759. static void
  760. bcmmulticast(void*v, uint8_t*u, int i)
  761. {
  762. }
  763. static int
  764. bcmpnp(Ether* edev)
  765. {
  766. Ctlr *ctlr;
  767. static int done;
  768. if(done == 0){
  769. bcmpci();
  770. done = 1;
  771. }
  772. redux:
  773. for(ctlr = bcmhead; ; ctlr = ctlr->next) {
  774. if(ctlr == nil)
  775. return -1;
  776. if(ctlr->active)
  777. continue;
  778. if(edev->port == 0 || edev->port == ctlr->port) {
  779. ctlr->active = 1;
  780. break;
  781. }
  782. }
  783. ctlr->ether = edev;
  784. edev->ctlr = ctlr;
  785. edev->port = ctlr->port;
  786. edev->irq = ctlr->pdev->intl;
  787. edev->tbdf = ctlr->pdev->tbdf;
  788. edev->interrupt = bcminterrupt;
  789. edev->ifstat = bcmifstat;
  790. edev->transmit = bcmtransmit;
  791. edev->multicast = bcmmulticast;
  792. edev->promiscuous = bcmpromiscuous;
  793. edev->arg = edev;
  794. edev->mbps = 1000;
  795. if(bcminit(edev) == -1)
  796. goto redux;
  797. return 0;
  798. }
  799. void
  800. etherbcmlink(void)
  801. {
  802. addethercard("bcm57xx", bcmpnp);
  803. }