etherbcm4401.c 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136
  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 BCM4401.
  11. */
  12. #include "u.h"
  13. #include "lib.h"
  14. #include "mem.h"
  15. #include "dat.h"
  16. #include "fns.h"
  17. #include "io.h"
  18. #include "ip.h"
  19. #include "etherif.h"
  20. #include "ethermii.h"
  21. enum { /* Broadcom Registers */
  22. Bdctl = 0x0000, /* Device Control */
  23. Bis = 0x0020, /* Interrupt Status */
  24. Bim = 0x0024, /* Interrupt Mask */
  25. Bmctl = 0x00A8, /* MAC Control */
  26. Blictl = 0x0100, /* Lazy Interrupt Control */
  27. TDMActl = 0x0200, /* Tx DMA Control */
  28. TDMAra = 0x0204, /* Tx DMA Ring Address */
  29. TDMAld = 0x0208, /* Tx DMA Last Descriptor */
  30. TDMAstatus = 0x020C, /* Tx DMA Status */
  31. RDMActl = 0x0210, /* Rx DMA Control */
  32. RDMAra = 0x0214, /* Rx DMA Ring Address */
  33. RDMAld = 0x0218, /* Rx DMA Last Descriptor */
  34. RDMAstatus = 0x021C, /* Rx DMA Status */
  35. Rxcfg = 0x0400, /* Rx Config */
  36. Rxmax = 0x0404, /* Rx Max. Packet Length */
  37. Txmax = 0x0408, /* Tx Max. Packet Length */
  38. MDIOctl = 0x0410, /* */
  39. MDIOdata = 0x0414, /* */
  40. MDIOstatus = 0x041C, /* */
  41. CAMdlo = 0x0420, /* CAM Data Low */
  42. CAMdhi = 0x0424, /* CAM Data High */
  43. CAMctl = 0x0428, /* CAM Control */
  44. EMACctl = 0x042C, /* */
  45. EMACtxwmark = 0x0434, /* Transmit Watermark */
  46. MIBctl = 0x0438, /* */
  47. MIB = 0x0500, /* */
  48. Eeprom = 0x1000, /* EEPROM base */
  49. Eao = Eeprom+78, /* MAC address offset */
  50. Pao = Eeprom+90, /* Phy address offset */
  51. };
  52. enum { /* Bdctl */
  53. Bpfe = 0x00000080, /* Pattern Filtering Enable */
  54. Bipp = 0x00000400, /* Internal PHY Present */
  55. Bpme = 0x00001000, /* PHY Mode Enable */
  56. Bpmce = 0x00002000, /* PHY Mode Clock Enable */
  57. Bepr = 0x00008000, /* External PHY Reset */
  58. };
  59. enum { /* Bis/Bim */
  60. Ilc = 0x00000020, /* Link Change */
  61. Ipme = 0x00000040, /* Power Management Event */
  62. Igpt = 0x00000080, /* General Purpose Timeout */
  63. Idesce = 0x00000400, /* Descriptor Error */
  64. Idatae = 0x00000800, /* Data Error */
  65. Idpe = 0x00001000, /* Descriptor Protocol Error */
  66. Irdu = 0x00002000, /* Rx Descriptor Underflow */
  67. Irfo = 0x00004000, /* Rx FIFO Overflow */
  68. Itfu = 0x00008000, /* Tx FIFO Underflow */
  69. Ir = 0x00010000, /* Rx */
  70. It = 0x01000000, /* Tx */
  71. Ie = 0x04000000, /* EMAC */
  72. Imw = 0x08000000, /* MII Write */
  73. Imr = 0x10000000, /* MII Read */
  74. Ierror = Itfu|Irfo|Irdu|Idpe|Idatae|Idesce,
  75. };
  76. enum { /* Bmctl */
  77. Mcge = 0x00000001, /* CRC32 Generation Enable */
  78. Mppd = 0x00000004, /* Onchip PHY Power Down */
  79. Mped = 0x00000008, /* Onchip PHY Energy Detected */
  80. MlcMASK = 0x000000E0, /* Onchip PHY LED Control */
  81. MlcSHIFT = 5,
  82. };
  83. enum { /* Blictl */
  84. MtoMASK = 0x00FFFFFF, /* Timeout */
  85. MtoSHIFT = 0,
  86. MfcMASK = 0xFF000000, /* Frame Count */
  87. MfcSHIFT = 24,
  88. };
  89. enum { /* TDMActl */
  90. Te = 0x00000001, /* Enable */
  91. };
  92. enum { /* RDMActl */
  93. Re = 0x00000001, /* Enable */
  94. RfoMASK = 0x000000FE, /* Receive Frame Offset */
  95. RfoSHIFT = 1,
  96. };
  97. enum { /* RDMAstatus */
  98. DcdMASK = 0x00000FFF, /* Current Descriptor */
  99. DcdSHIFT = 0,
  100. Dactive = 0x00001000, /* Active */
  101. Didle = 0x00002000, /* Idle */
  102. Dstopped = 0x00003000, /* Stopped */
  103. Dsm = 0x0000F000, /* State Mask */
  104. Dem = 0x000F0000, /* Error mask */
  105. };
  106. enum { /* MDIOctl */
  107. Mfreq = 0x0000000D, /* MDC Frequency (62.5MHz) */
  108. Mpe = 0x00000080, /* Preamble Enable */
  109. };
  110. enum { /* MDIOdata */
  111. Mack = 0x00020000, /* Ack */
  112. Mwop = 0x10000000, /* Write Op. */
  113. Mrop = 0x20000000, /* Read Op. */
  114. Msof = 0x40000000, /* Start of Frame */
  115. };
  116. enum { /* MDIOstatus */
  117. Mmi = 0x00000001, /* MDIO Interrupt */
  118. };
  119. enum { /* Rxcfg */
  120. Rbd = 0x00000001, /* Broadcast Disable */
  121. Raam = 0x00000002, /* Accept All Multicast */
  122. Rdtx = 0x00000004, /* Disable while Transmitting */
  123. Rpe = 0x00000008, /* Promiscuous Enable */
  124. Rle = 0x00000010, /* Loopback Enable */
  125. Rfce = 0x00000020, /* Flow Control Enable */
  126. Rafcf = 0x00000040, /* Accept Unicast FC Frame */
  127. Rrf = 0x00000080, /* Reject Filter */
  128. };
  129. enum { /* CAMctl */
  130. Ce = 0x00000001, /* Enable */
  131. Cms = 0x00000002, /* Mask Select */
  132. Cr = 0x00000004, /* Read */
  133. Cw = 0x00000008, /* Write */
  134. CiMASK = 0x003F0000, /* Index Mask */
  135. CiSHIFT = 16,
  136. Cbusy = 0x80000000, /* Busy */
  137. };
  138. enum { /* CAMdhi */
  139. Cv = 0x00010000, /* Valid */
  140. };
  141. enum { /* EMACctl */
  142. Eena = 0x00000001, /* Enable */
  143. Edis = 0x00000002, /* Disable */
  144. Erst = 0x00000004, /* Reset */
  145. Eeps = 0x00000008, /* External PHY Select */
  146. };
  147. enum { /* MIBctl */
  148. MIBcor = 0x00000001, /* Clear On Read */
  149. };
  150. enum { /* SonicsBackplane Registers */
  151. SBs2pci2 = 0x0108, /* Sonics to PCI translation */
  152. SBias = 0x0F90, /* Initiator Agent State */
  153. SBim = 0x0F94, /* Interrupt Mask */
  154. SBtslo = 0x0F98, /* Target State Low */
  155. SBtshi = 0x0F9C, /* Target State High */
  156. };
  157. enum { /* SBs2pci2 */
  158. Spref = 0x00000004, /* Prefetch Enable */
  159. Sburst = 0x00000008, /* Burst Enable */
  160. };
  161. enum { /* SBias */
  162. Sibe = 0x00020000, /* In-Band Error */
  163. Sto = 0x00040000, /* Timeout */
  164. };
  165. enum { /* SBim */
  166. Senet0 = 0x00000002, /* Ethernet 0 */
  167. };
  168. enum { /* SBtslo */
  169. Sreset = 0x00000001, /* */
  170. Sreject = 0x00000002, /* */
  171. Sclock = 0x00010000, /* */
  172. Sfgc = 0x00020000, /* Force Gated Clocks On */
  173. };
  174. enum { /* SBtshi */
  175. Sserr = 0x00000001, /* */
  176. Sbusy = 0x00000004, /* */
  177. };
  178. // dma descriptor. must be 4096 aligned and fit in single 4096 page.
  179. // rx and tx descriptors can't share the same page apparently so we'll
  180. // have to malloc that even though we don't use it all.
  181. // descriptors are only ever read by the nic, not written back.
  182. typedef struct {
  183. uint32_t control;
  184. uint32_t address;
  185. } DD;
  186. enum { /* DD.control */
  187. DDbbcMASK = 0x00001FFF, /* Buffer Byte Count */
  188. DDbbcSHIFT = 0,
  189. DDeot = 0x10000000, /* End of Descriptor Table */
  190. DDioc = 0x20000000, /* Interrupt on Completion */
  191. DDeof = 0x40000000, /* End of Frame */
  192. DDsof = 0x80000000, /* Start of Frame */
  193. };
  194. // the core returns 8 bytes - 4 bytes length and status
  195. // and 4 bytes undefined.
  196. // so we pad for alignment of the data...? but why in the struct
  197. // since the offset is defined in a register and the struct is
  198. // 28 and the offset is usually set to 30?
  199. // bollocks. it looks to me like the status written is 28 bytes.
  200. typedef struct {
  201. uint32_t status;
  202. uint32_t undefined;
  203. uint32_t pad[5];
  204. void* bp; /* software */
  205. uint8_t data[]; /* flexible array member... */
  206. } H;
  207. enum { /* H.status */
  208. HflMASK = 0x0000FFFF, /* Frame Length */
  209. HflSHIFT = 0,
  210. Hfo = 0x00010000, /* FIFO Overflow */
  211. Hce = 0x00020000, /* CRC Error */
  212. Hse = 0x00040000, /* Symbol Error */
  213. Hodd = 0x00080000, /* Odd Number of Nibbles */
  214. Hl = 0x00100000, /* Frame too Large */
  215. Hmf = 0x00200000, /* Multicast Frame */
  216. Hbf = 0x00400000, /* Broadcast Frame */
  217. Hpf = 0x00800000, /* Promiscuous Frame */
  218. Hlbf = 0x08000000, /* Last Buffer in Frame */
  219. };
  220. enum {
  221. Ncam = 64,
  222. Nmib = 55,
  223. SBPCIWADDR = 0x40000000,
  224. Nrd = 8,
  225. Ntd = 8,
  226. Rbhsz = sizeof(H), /* 28 + space for a pointer */
  227. Rbdsz = 1522+Rbhsz,
  228. };
  229. typedef struct Ctlr Ctlr;
  230. typedef struct Ctlr {
  231. uint32_t port;
  232. Pcidev* pcidev;
  233. Ctlr* next;
  234. int active;
  235. int id;
  236. uint8_t pa[Eaddrlen];
  237. void* nic;
  238. QLock alock; /* attach */
  239. void* alloc; /* */
  240. uint32_t im;
  241. uint32_t rcr;
  242. Lock tlock; /* transmit */
  243. DD* td; /* descriptor ring */
  244. Block** tb; /* transmit buffers */
  245. int ntd;
  246. int tdh; /* head - producer index (host) */
  247. int tdt; /* tail - consumer index (NIC) */
  248. int ntdfree;
  249. int ntq;
  250. Lock rlock; /* receive */
  251. DD* rd; /* descriptor ring */
  252. void** rb; /* receive buffers */
  253. int nrd;
  254. int rdh; /* head - producer index (NIC) */
  255. int rdt; /* tail - consumer index (host) */
  256. int nrdfree;
  257. DD* tddr;
  258. Mii* mii;
  259. uint intr; /* statistics */
  260. uint lintr;
  261. uint lsleep;
  262. uint rintr;
  263. uint tintr;
  264. uint txdu;
  265. uint mib[Nmib];
  266. } Ctlr;
  267. #define csr8r(c, r) (*((uint8_t*)((c)->nic)+(r)))
  268. #define csr16r(c, r) (*((uint16_t*)((c)->nic)+((r)/2)))
  269. #define csr32p(c, r) ((uint32_t*)((c)->nic)+((r)/4))
  270. #define csr32r(c, r) (*csr32p(c, r))
  271. #define csr32w(c, r, v) (*csr32p(c, r) = (v))
  272. #define csr32a(c, r) { uint32_t dummy = csr32r(c, r); USED(dummy);}
  273. // hmmm. maybe we need a csr32wrb instead, write and read back?
  274. static Ctlr* bcm4401ctlrhead;
  275. static Ctlr* bcm4401ctlrtail;
  276. static char* statistics[Nmib] = {
  277. "Tx Good Octets",
  278. "Tx Good Pkts",
  279. "Tx Octets",
  280. "Tx Pkts",
  281. "Tx Broadcast Pkts",
  282. "Tx Multicast Pkts",
  283. "Tx (64)",
  284. "Tx (65-127)",
  285. "Tx (128-255)",
  286. "Tx (256-511)",
  287. "Tx (512-1023)",
  288. "Tx (1024-max)",
  289. "Tx Jabber Pkts",
  290. "Tx Oversize Pkts",
  291. "Tx Fragment Pkts",
  292. "Tx Underruns",
  293. "Tx Total Cols",
  294. "Tx Single Cols",
  295. "Tx Multiple Cols",
  296. "Tx Excessive Cols",
  297. "Tx Late Cols",
  298. "Tx Defered",
  299. "Tx Carrier Lost",
  300. "Tx Pause Pkts",
  301. nil,
  302. nil,
  303. nil,
  304. nil,
  305. nil,
  306. nil,
  307. nil,
  308. nil,
  309. "Rx Good Octets",
  310. "Rx Good Pkts",
  311. "Rx Octets",
  312. "Rx Pkts",
  313. "Rx Broadcast Pkts",
  314. "Rx Multicast Pkts",
  315. "Rx (64)",
  316. "Rx (65-127)",
  317. "Rx (128-255)",
  318. "Rx (256-511)",
  319. "Rx (512-1023)",
  320. "Rx (1024-Max)",
  321. "Rx Jabber Pkts",
  322. "Rx Oversize Pkts",
  323. "Rx Fragment Pkts",
  324. "Rx Missed Pkts",
  325. "Rx CRC Align Errs",
  326. "Rx Undersize",
  327. "Rx CRC Errs",
  328. "Rx Align Errs",
  329. "Rx Symbol Errs",
  330. "Rx Pause Pkts",
  331. "Rx Non-pause Pkts",
  332. };
  333. static void
  334. bcm4401mib(Ctlr* ctlr, uint* mib)
  335. {
  336. int i;
  337. uint32_t r;
  338. csr32w(ctlr, MIBctl, MIBcor);
  339. for(i = 0; i < Nmib; i++){
  340. r = csr32r(ctlr, MIB+i*sizeof(uint32_t));
  341. if(mib == nil)
  342. continue;
  343. if(statistics[i] != nil)
  344. *mib += r;
  345. mib++;
  346. }
  347. }
  348. static int32_t
  349. bcm4401ifstat(Ether* edev, void* a, int32_t n, uint32_t offset)
  350. {
  351. char *p;
  352. Ctlr *ctlr;
  353. int i, l, r;
  354. ctlr = edev->ctlr;
  355. p = malloc(2*READSTR);
  356. l = 0;
  357. l += snprint(p+l, 2*READSTR-l, "intr: %ud\n", ctlr->intr);
  358. l += snprint(p+l, 2*READSTR-l, "lintr: %ud\n", ctlr->lintr);
  359. l += snprint(p+l, 2*READSTR-l, "lsleep: %ud\n", ctlr->lsleep);
  360. l += snprint(p+l, 2*READSTR-l, "rintr: %ud\n", ctlr->rintr);
  361. l += snprint(p+l, 2*READSTR-l, "tintr: %ud\n", ctlr->tintr);
  362. if(ctlr->mii != nil && ctlr->mii->curphy != nil){
  363. l += snprint(p+l, 2*READSTR, "phy: ");
  364. for(i = 0; i < NMiiPhyr; i++){
  365. if(i && ((i & 0x07) == 0))
  366. l += snprint(p+l, 2*READSTR-l, "\n ");
  367. r = miimir(ctlr->mii, i);
  368. l += snprint(p+l, 2*READSTR-l, " %4.4ux", r);
  369. }
  370. snprint(p+l, 2*READSTR-l, "\n");
  371. }
  372. snprint(p+l, 2*READSTR-l, "\n");
  373. n = readstr(offset, a, n, p);
  374. free(p);
  375. return n;
  376. }
  377. static void
  378. _bcm4401promiscuous(Ctlr* ctlr, int on)
  379. {
  380. uint32_t r;
  381. r = csr32r(ctlr, CAMctl);
  382. if(on){
  383. ctlr->rcr |= Rpe;
  384. r &= ~Ce;
  385. }
  386. else{
  387. ctlr->rcr &= ~Rpe;
  388. r |= Ce;
  389. }
  390. csr32w(ctlr, Rxcfg, ctlr->rcr);
  391. csr32w(ctlr, CAMctl, r);
  392. }
  393. static void
  394. bcm4401promiscuous(void* arg, int on)
  395. {
  396. _bcm4401promiscuous(((Ether*)arg)->ctlr, on);
  397. }
  398. static void
  399. bcm4401multicast(void* arg, uint8_t* addr, int on)
  400. {
  401. USED(arg, addr, on);
  402. }
  403. static void
  404. bcm4401attach(Ether* edev)
  405. {
  406. Ctlr *ctlr;
  407. ctlr = edev->ctlr;
  408. qlock(&ctlr->alock);
  409. if(ctlr->alloc != nil){
  410. qunlock(&ctlr->alock);
  411. return;
  412. }
  413. if(waserror()){
  414. nexterror();
  415. }
  416. qunlock(&ctlr->alock);
  417. poperror();
  418. }
  419. static void
  420. bcm4401transmit(Ether* edev)
  421. {
  422. DD *d;
  423. Block *bp;
  424. Ctlr *ctlr;
  425. int control, s, tdh, tdt;
  426. RingBuf *ring;
  427. ctlr = edev->ctlr;
  428. ilock(&ctlr->tlock);
  429. s = csr32r(ctlr, TDMAstatus);
  430. tdt = ((s & DcdMASK) >> DcdSHIFT)/sizeof(DD);
  431. for(tdh = ctlr->tdh; tdh != tdt; tdh = NEXT(tdh, ctlr->ntd)){
  432. d = &ctlr->td[tdh];
  433. /*
  434. * Check errors and log here.
  435. */
  436. SET(control);
  437. USED(control);
  438. // seems to be no way to tell whether the packet
  439. // went out or not or had errors?
  440. /*
  441. * Free it up.
  442. * Need to clean the descriptor here? Not really.
  443. * Simple freeb for now (no chain and freeblist).
  444. * Use ntq count for now.
  445. */
  446. freeb(ctlr->tb[tdh]);
  447. ctlr->tb[tdh] = nil;
  448. d->control &= DDeot;
  449. d->address = 0;
  450. ctlr->ntq--;
  451. }
  452. ctlr->tdh = tdh;
  453. tdt = ctlr->tdt;
  454. while(ctlr->ntq < (ctlr->ntd-1)){
  455. ring = &edev->tb[edev->ti];
  456. if(ring->owner != Interface)
  457. break;
  458. bp = allocb(ring->len);
  459. memmove(bp->wp, ring->pkt, ring->len);
  460. memmove(bp->wp+Eaddrlen, edev->ea, Eaddrlen);
  461. bp->wp += ring->len;
  462. ring->owner = Host;
  463. edev->ti = NEXT(edev->ti, edev->ntb);
  464. d = &ctlr->td[tdt];
  465. d->address = PCIWADDR(bp->rp) + SBPCIWADDR;
  466. ctlr->tb[tdt] = bp;
  467. wmb();
  468. d->control |= DDsof|DDeof|((BLEN(bp)<<DDbbcSHIFT) & DDbbcMASK);
  469. d->control |= DDioc;
  470. tdt = NEXT(tdt, ctlr->ntd);
  471. ctlr->ntq++;
  472. }
  473. if(tdt != ctlr->tdt){
  474. ctlr->tdt = tdt;
  475. csr32w(ctlr, TDMAld, tdt*sizeof(DD));
  476. }
  477. else if(ctlr->ntq >= (ctlr->ntd-1))
  478. ctlr->txdu++;
  479. iunlock(&ctlr->tlock);
  480. }
  481. static void
  482. bcm4401replenish(Ctlr* ctlr)
  483. {
  484. DD *d;
  485. int rdt;
  486. void *bp;
  487. H* h;
  488. rdt = ctlr->rdt;
  489. while(NEXT(rdt, ctlr->nrd) != ctlr->rdh){
  490. d = &ctlr->rd[rdt];
  491. if((bp = ctlr->rb[rdt]) == nil){
  492. /*
  493. * simple allocation for now
  494. */
  495. bp = malloc(Rbdsz);
  496. ctlr->rb[rdt] = bp;
  497. }
  498. d->address = PCIWADDR(bp) + SBPCIWADDR;
  499. d->control |= (((Rbdsz-Rbhsz)<<DDbbcSHIFT) & DDbbcMASK);
  500. h = ctlr->rb[rdt];
  501. h->status = 0;
  502. h->bp = bp;
  503. wmb();
  504. rdt = NEXT(rdt, ctlr->nrd);
  505. ctlr->nrdfree++;
  506. }
  507. ctlr->rdt = rdt;
  508. }
  509. static void
  510. bcm4401receive(Ether* edev)
  511. {
  512. DD *d;
  513. H* h;
  514. uint8_t *p;
  515. int len, rdh, rdt, s;
  516. Ctlr *ctlr;
  517. uint32_t status;
  518. RingBuf *ring;
  519. ctlr = edev->ctlr;
  520. s = csr32r(ctlr, RDMAstatus);
  521. rdt = ((s & DcdMASK) >> DcdSHIFT)/sizeof(DD);
  522. for(rdh = ctlr->rdh; rdh != rdt; rdh = NEXT(rdh, ctlr->nrd)){
  523. d = &ctlr->rd[rdh];
  524. h = ctlr->rb[rdh];
  525. p = h->data;
  526. status = h->status;
  527. len = ((status & HflMASK)>>HflSHIFT);
  528. if(len == 0 ||len >(Rbdsz-Rbhsz))
  529. continue;
  530. if(!(status & (Hl|Hodd|Hse|Hce|Hfo))){
  531. ring = &edev->rb[edev->ri];
  532. if(ring->owner == Interface){
  533. ring->owner = Host;
  534. ring->len = len;
  535. memmove(ring->pkt, p, len-4);
  536. edev->ri = NEXT(edev->ri, edev->nrb);
  537. }
  538. }
  539. else{
  540. /*
  541. * Error stuff here.
  542. print("status %8.8uX\n", status);
  543. */
  544. }
  545. h->status = 0;
  546. d->address = 0;
  547. d->control &= DDeot;
  548. ctlr->nrdfree--;
  549. }
  550. ctlr->rdh = rdh;
  551. if(ctlr->nrdfree < ctlr->nrd/2)
  552. bcm4401replenish(ctlr);
  553. }
  554. static void
  555. bcm4401interrupt(Ureg*, void* arg)
  556. {
  557. Ctlr *ctlr;
  558. Ether *edev;
  559. uint32_t im, is;
  560. edev = arg;
  561. ctlr = edev->ctlr;
  562. ctlr->intr++;
  563. for(;;){
  564. is = csr32r(ctlr, Bis);
  565. im = csr32r(ctlr, Bim);
  566. is &= im;
  567. if(is == 0)
  568. break;
  569. csr32w(ctlr, Bis, is);
  570. csr32a(ctlr, Bis);
  571. if(is & Ir)
  572. bcm4401receive(edev);
  573. if(is & It)
  574. bcm4401transmit(edev);
  575. if(is & ~(It|Ir))
  576. panic("is %ux\n", is);
  577. }
  578. }
  579. static int
  580. bcm4401spin(u32int* csr32, int bit, int set, int µs)
  581. {
  582. int t;
  583. u32int r;
  584. if(µs < 10)
  585. µs = 10;
  586. for(t = 0; t < µs; t += 10){
  587. r = *csr32;
  588. if(set){
  589. if(r & bit)
  590. return 0;
  591. }
  592. else if(!(r & bit))
  593. return 0;
  594. microdelay(10);
  595. }
  596. return -1;
  597. }
  598. static void
  599. bcm4401cam(Ctlr* ctlr, int cvix, uint8_t* a)
  600. {
  601. csr32w(ctlr, CAMdlo, (a[2]<<24)|(a[3]<<16)|(a[4]<<8)|a[5]);
  602. csr32w(ctlr, CAMdhi, (cvix & Cv)|(a[0]<<8)|a[1]);
  603. csr32w(ctlr, CAMctl, ((cvix<<CiSHIFT) & CiMASK)|Cw);
  604. bcm4401spin(csr32p(ctlr, CAMctl), Cbusy, 0, 1000);
  605. }
  606. static void
  607. bcm4401sbreset(Ctlr* ctlr)
  608. {
  609. uint32_t bar0, r;
  610. /*
  611. * If the core is running, stop it.
  612. */
  613. r = csr32r(ctlr, SBtslo);
  614. if((r & (Sclock|Sreject|Sreset)) == Sclock){
  615. csr32w(ctlr, Blictl, 0);
  616. csr32w(ctlr, EMACctl, Edis);
  617. bcm4401spin(csr32p(ctlr, EMACctl), Edis, 0, 1000);
  618. csr32w(ctlr, TDMActl, 0);
  619. r = csr32r(ctlr, RDMAstatus);
  620. if(r & Dem)
  621. bcm4401spin(csr32p(ctlr, RDMAstatus), Didle, 1, 1000);
  622. csr32w(ctlr, RDMActl, 0);
  623. csr32w(ctlr, EMACctl, Erst);
  624. }
  625. else{
  626. // set up sonic pci
  627. // reg80 holds the window space accessed - 0x18000000 is
  628. // the emac, 0x18002000 are the pci registers
  629. bar0 = pcicfgr32(ctlr->pcidev, 0x80);
  630. pcicfgw32(ctlr->pcidev, 0x80, 0x18002000);
  631. r = pcicfgr32(ctlr->pcidev, SBim);
  632. r |= Senet0;
  633. pcicfgw32(ctlr->pcidev, SBim, r);
  634. r = pcicfgr32(ctlr->pcidev, SBs2pci2);
  635. r |= Sburst|Spref;
  636. pcicfgw32(ctlr->pcidev, SBs2pci2, r);
  637. pcicfgw32(ctlr->pcidev, 0x80, bar0);
  638. }
  639. // disable core
  640. // must return if core is already in reset
  641. // set the reject bit
  642. // spin until reject is set
  643. // spin until sbtmstatehigh.busy is clear
  644. // set reset and reject while enabling the clocks
  645. // leave reset and reject asserted
  646. r = csr32r(ctlr, SBtslo);
  647. if(!(r & Sreset)){
  648. csr32w(ctlr, SBtslo, Sclock|Sreject);
  649. bcm4401spin(csr32p(ctlr, SBtslo), Sreject, 1, 1000000);
  650. bcm4401spin(csr32p(ctlr, SBtshi), Sbusy, 0, 1000000);
  651. csr32w(ctlr, SBtslo, Sfgc|Sclock|Sreject|Sreset);
  652. csr32a(ctlr, SBtslo);
  653. microdelay(10);
  654. csr32w(ctlr, SBtslo, Sreject|Sreset);
  655. microdelay(10);
  656. }
  657. // core reset - initialisation, surely?
  658. /*
  659. * Now do the initialization sequence.
  660. */
  661. // set reset while enabling the clock and forcing them on
  662. // throughout the core
  663. // clear any error bits that may be o
  664. // clear reset and allow it to propagate throughout the core
  665. // leave clock enabled
  666. csr32w(ctlr, SBtslo, Sfgc|Sclock|Sreset);
  667. csr32a(ctlr, SBtslo);
  668. microdelay(1);
  669. if(csr32r(ctlr, SBtshi) & Sserr)
  670. csr32w(ctlr, SBtshi, 0);
  671. r = csr32r(ctlr, SBias);
  672. if(r & (Sto|Sibe))
  673. csr32w(ctlr, SBias, r & ~(Sto|Sibe));
  674. csr32w(ctlr, SBtslo, Sfgc|Sclock);
  675. csr32a(ctlr, SBtslo);
  676. microdelay(1);
  677. csr32w(ctlr, SBtslo, Sclock);
  678. csr32a(ctlr, SBtslo);
  679. microdelay(1);
  680. }
  681. static int
  682. bcm4401detach(Ctlr* ctlr)
  683. {
  684. /*
  685. * Soft reset the controller.
  686. */
  687. bcm4401sbreset(ctlr);
  688. // need to clean up software state somewhere
  689. return 0;
  690. }
  691. static int
  692. bcm4401init(Ctlr* ctlr)
  693. {
  694. uint32_t r;
  695. // Clear the stats on reset.
  696. bcm4401mib(ctlr, nil);
  697. // Enable CRC32, set proper LED modes and power on PHY
  698. csr32w(ctlr, Bmctl, ((7<<MlcSHIFT) & MlcMASK)|Mcge);
  699. csr32w(ctlr, Blictl, ((1<<MfcSHIFT) & MfcMASK));
  700. // is this the max length of a packet or the max length of the buffer?
  701. // packet is 1522 (mtu+header+crc+vlantag = 1522), buffer is that +30
  702. // for prepended rx header
  703. csr32w(ctlr, Rxmax, Rbdsz);
  704. csr32w(ctlr, Txmax, 1522);
  705. // no explanation of this anywhere
  706. csr32w(ctlr, EMACtxwmark, 56);
  707. // this is software init - elsewhere before this (attach?)
  708. ctlr->ntd = Ntd;
  709. ctlr->td = mallocalign(4096/*sizeof(DD)*ctlr->ntd*/, 4096, 0, 0);
  710. ctlr->td[ctlr->ntd-1].control = DDeot;
  711. ctlr->tdh = ctlr->tdt = 0;
  712. ctlr->tb = malloc(ctlr->ntd*sizeof(Block*));
  713. ctlr->ntq = 0;
  714. // ring dma address is the phys address of the rx ring
  715. // plus where the sb core sees the phys memory base
  716. csr32w(ctlr, TDMAra, PCIWADDR(ctlr->td)+SBPCIWADDR);
  717. csr32w(ctlr, TDMActl, Te);
  718. // this is software init - elsewhere (attach?)
  719. ctlr->nrd = Nrd;
  720. ctlr->rd = mallocalign(4096/*sizeof(DD)*ctlr->nrd*/, 4096, 0, 0);
  721. ctlr->rd[ctlr->nrd-1].control = DDeot;
  722. ctlr->rdh = ctlr->rdt = 0;
  723. ctlr->rb = malloc(ctlr->nrd*sizeof(void*));
  724. bcm4401replenish(ctlr);
  725. csr32w(ctlr, RDMAra, PCIWADDR(ctlr->rd)+SBPCIWADDR);
  726. csr32w(ctlr, RDMAld, 0);
  727. // pre-packet header (usually 30)
  728. csr32w(ctlr, RDMActl, ((Rbhsz<<RfoSHIFT) & RfoMASK)|Re);
  729. csr32w(ctlr, RDMAld, (ctlr->nrd)*sizeof(DD));
  730. // this is done in mib read too - only need once
  731. csr32w(ctlr, MIBctl, MIBcor);
  732. // EMACctl? ENETctl?
  733. r = csr32r(ctlr, EMACctl);
  734. csr32w(ctlr, EMACctl, Eena|r);
  735. return 0;
  736. }
  737. static int
  738. bcm4401miimir(Mii* mii, int pa, int ra)
  739. {
  740. uint32_t r;
  741. int timeo;
  742. Ctlr *ctlr;
  743. ctlr = mii->ctlr;
  744. csr32w(ctlr, MDIOstatus, 1);
  745. csr32w(ctlr, MDIOdata, Msof|Mrop|(pa<<23)|(ra<<18)|Mack);
  746. for(r = timeo = 0; timeo < 100; timeo++){
  747. if((r = csr32r(ctlr, MDIOstatus)) & Mmi)
  748. break;
  749. microdelay(10);
  750. }
  751. if(!(r & Mmi))
  752. return -1;
  753. return csr32r(ctlr, MDIOdata) & 0xFFFF;
  754. }
  755. static int
  756. bcm4401miimiw(Mii* mii, int pa, int ra, int data)
  757. {
  758. uint32_t r;
  759. int timeo;
  760. Ctlr *ctlr;
  761. ctlr = mii->ctlr;
  762. csr32w(ctlr, MDIOstatus, 1);
  763. csr32w(ctlr, MDIOdata, Msof|Mwop|(pa<<23)|(ra<<18)|Mack|data);
  764. for(r = timeo = 0; timeo < 100; timeo++){
  765. if((r = csr32r(ctlr, MDIOstatus)) & Mmi)
  766. break;
  767. microdelay(10);
  768. }
  769. if(!(r & Mmi))
  770. return -1;
  771. return csr32r(ctlr, MDIOdata) & 0xFFFF;
  772. }
  773. static int
  774. bcm4401reset(Ctlr* ctlr)
  775. {
  776. int i;
  777. uint32_t r;
  778. MiiPhy *phy;
  779. uint8_t ea[Eaddrlen];
  780. // disable ints - here or where?
  781. csr32w(ctlr, Bim, 0);
  782. csr32a(ctlr, Bim);
  783. if(bcm4401detach(ctlr) < 0)
  784. return -1;
  785. // make the phy accessible; depends on internal/external.
  786. csr32w(ctlr, MDIOctl, Mpe|Mfreq);
  787. r = csr32r(ctlr, Bdctl);
  788. if(!(r & Bipp))
  789. csr32w(ctlr, EMACctl, Eeps);
  790. else if(r & Bepr){
  791. csr32w(ctlr, Bdctl, r & ~Bepr);
  792. microdelay(100);
  793. }
  794. /*
  795. * Read the MAC address.
  796. */
  797. for(i = 0; i < Eaddrlen; i += 2){
  798. ctlr->pa[i] = csr8r(ctlr, Eao+i+1);
  799. ctlr->pa[i+1] = csr8r(ctlr, Eao+i);
  800. }
  801. // initialise the mac address and cam
  802. bcm4401cam(ctlr, Cv|0, ctlr->pa);
  803. memset(ea, 0, Eaddrlen);
  804. for(i = 1; i < Ncam; i++)
  805. bcm4401cam(ctlr, i, ea);
  806. // default initial Rxcfg. set Rxcfg reg here? call promiscuous?
  807. ctlr->rcr = 0/*Raam*/;
  808. bcm4401init(ctlr);
  809. _bcm4401promiscuous(ctlr, 0);
  810. // default initial interrupt mask.
  811. ctlr->im = Ierror|It|Ir|Igpt;
  812. csr32w(ctlr, Bim, ctlr->im);
  813. csr32a(ctlr, Bim);
  814. /*
  815. * Link management.
  816. */
  817. if((ctlr->mii = malloc(sizeof(Mii))) == nil)
  818. return -1;
  819. ctlr->mii->mir = bcm4401miimir;
  820. ctlr->mii->miw = bcm4401miimiw;
  821. ctlr->mii->ctlr = ctlr;
  822. /*
  823. * Read the PHY address.
  824. */
  825. r = csr8r(ctlr, Pao);
  826. r = 1<<(r & 0x1F);
  827. if(mii(ctlr->mii, r) == 0 || (phy = ctlr->mii->curphy) == nil){
  828. free(ctlr->mii);
  829. ctlr->mii = nil;
  830. return -1;
  831. }
  832. miireset(ctlr->mii);
  833. // need to do some phy-specific init somewhere - why not here?
  834. // enable activity led
  835. i = miimir(ctlr->mii, 26);
  836. miimiw(ctlr->mii, 26, i & 0x7FFF);
  837. // enable traffic meter led mode
  838. i = miimir(ctlr->mii, 27);
  839. miimiw(ctlr->mii, 27, i|0x0040);
  840. print("oui %#ux phyno %d\n", phy->oui, phy->phyno);
  841. // need to set rxconfig before this and then call promiscuous
  842. // later once we know the link settings
  843. // By default, auto-negotiate PAUSE
  844. miiane(ctlr->mii, ~0, ~0, ~0);
  845. // set rcr according to pause, etc.
  846. return 0;
  847. }
  848. static void
  849. bcm4401pci(void)
  850. {
  851. Pcidev *p;
  852. Ctlr *ctlr;
  853. int i, port;
  854. uint32_t bar;
  855. p = nil;
  856. while(p = pcimatch(p, 0, 0)){
  857. if(p->ccrb != 0x02 || p->ccru != 0)
  858. continue;
  859. switch((p->did<<16)|p->vid){
  860. default:
  861. continue;
  862. case (0x170C<<16)|0x14E4: /* BCM4401-B0 */
  863. case (0x4401<<16)|0x14E4: /* BCM4401 */
  864. case (0x4402<<16)|0x14E4: /* BCM440? */
  865. break;
  866. }
  867. bar = p->mem[0].bar;
  868. if(bar & 0x01){
  869. port = bar & ~0x01;
  870. if(ioalloc(port, p->mem[0].size, 0, "bcm4401") < 0){
  871. print("bcm4401: port %#ux in use\n", port);
  872. continue;
  873. }
  874. }
  875. else{
  876. port = upamalloc(bar & ~0x0F, p->mem[0].size, 0);
  877. if(port == 0){
  878. print("bcm4401: can't map %#ux\n", bar);
  879. continue;
  880. }
  881. }
  882. ctlr = malloc(sizeof(Ctlr));
  883. ctlr->port = port;
  884. ctlr->pcidev = p;
  885. ctlr->id = (p->did<<16)|p->vid;
  886. ctlr->nic = KADDR(ctlr->port);
  887. if(pcigetpms(p) > 0){
  888. pcisetpms(p, 0);
  889. for(i = 0; i < 6; i++)
  890. pcicfgw32(p, PciBAR0+i*4, p->mem[i].bar);
  891. pcicfgw8(p, PciINTL, p->intl);
  892. pcicfgw8(p, PciLTR, p->ltr);
  893. pcicfgw8(p, PciCLS, p->cls);
  894. pcicfgw16(p, PciPCR, p->pcr);
  895. }
  896. if(bcm4401reset(ctlr)){
  897. if(bar & 0x01){
  898. /* may be empty... */
  899. iofree(port);
  900. }
  901. else
  902. upafree(port, p->mem[0].size);
  903. free(ctlr);
  904. continue;
  905. }
  906. pcisetbme(p);
  907. if(bcm4401ctlrhead != nil)
  908. bcm4401ctlrtail->next = ctlr;
  909. else
  910. bcm4401ctlrhead = ctlr;
  911. bcm4401ctlrtail = ctlr;
  912. }
  913. }
  914. static int
  915. bcm4401pnp(Ether* edev)
  916. {
  917. Ctlr *ctlr;
  918. if(bcm4401ctlrhead == nil)
  919. bcm4401pci();
  920. /*
  921. * Any adapter matches if no edev->port is supplied,
  922. * otherwise the ports must match.
  923. */
  924. for(ctlr = bcm4401ctlrhead; ctlr != nil; ctlr = ctlr->next){
  925. if(ctlr->active)
  926. continue;
  927. if(edev->port == 0 || edev->port == ctlr->port){
  928. ctlr->active = 1;
  929. break;
  930. }
  931. }
  932. if(ctlr == nil)
  933. return -1;
  934. edev->ctlr = ctlr;
  935. edev->port = ctlr->port;
  936. edev->irq = ctlr->pcidev->intl;
  937. edev->tbdf = ctlr->pcidev->tbdf;
  938. edev->mbps = 100;
  939. memmove(edev->ea, ctlr->pa, Eaddrlen);
  940. /*
  941. * Linkage to the generic ethernet driver.
  942. */
  943. edev->attach = bcm4401attach;
  944. edev->transmit = bcm4401transmit;
  945. edev->interrupt = bcm4401interrupt;
  946. //TODO edev->detach = bcm4401detach;
  947. edev->ifstat = bcm4401ifstat;
  948. edev->ctl = nil;
  949. edev->arg = edev;
  950. edev->promiscuous = bcm4401promiscuous;
  951. edev->multicast = bcm4401multicast;
  952. return 0;
  953. }
  954. void
  955. etherbcm4401link(void)
  956. {
  957. addethercard("bcm4401", bcm4401pnp);
  958. }
  959. int
  960. etherbcm4401pnp(Ether* edev)
  961. {
  962. return bcm4401pnp(edev);
  963. }