etherfcc.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891
  1. /*
  2. * FCCn ethernet
  3. */
  4. #include "u.h"
  5. #include "../port/lib.h"
  6. #include "mem.h"
  7. #include "dat.h"
  8. #include "fns.h"
  9. #include "io.h"
  10. #include "imm.h"
  11. #include "../port/error.h"
  12. #include "../port/netif.h"
  13. #include "etherif.h"
  14. #include "../ppc/ethermii.h"
  15. #define DBG 1
  16. enum {
  17. Nrdre = 128, /* receive descriptor ring entries */
  18. Ntdre = 128, /* transmit descriptor ring entries */
  19. Rbsize = ETHERMAXTU+4, /* ring buffer size (+4 for CRC) */
  20. Bufsize = Rbsize+CACHELINESZ, /* extra room for alignment */
  21. };
  22. enum {
  23. /* ether-specific Rx BD bits */
  24. RxMiss= SBIT(7),
  25. RxeLG= SBIT(10),
  26. RxeNO= SBIT(11),
  27. RxeSH= SBIT(12),
  28. RxeCR= SBIT(13),
  29. RxeOV= SBIT(14),
  30. RxeCL= SBIT(15),
  31. RxError= (RxeLG|RxeNO|RxeSH|RxeCR|RxeOV|RxeCL), /* various error flags */
  32. /* ether-specific Tx BD bits */
  33. TxPad= SBIT(1), /* pad short frames */
  34. TxTC= SBIT(5), /* transmit CRC */
  35. TxeDEF= SBIT(6),
  36. TxeHB= SBIT(7),
  37. TxeLC= SBIT(8),
  38. TxeRL= SBIT(9),
  39. TxeUN= SBIT(14),
  40. TxeCSL= SBIT(15),
  41. /* psmr */
  42. CRCE= BIT(24), /* Ethernet CRC */
  43. FCE= BIT(10), /* flow control */
  44. PRO= BIT(9), /* promiscuous mode */
  45. FDE= BIT(5), /* full duplex ethernet */
  46. LPB= BIT(3), /* local protect bit */
  47. /* gfmr */
  48. ENET= 0xc, /* ethernet mode */
  49. ENT= BIT(27),
  50. ENR= BIT(26),
  51. TCI= BIT(2),
  52. /* FCC function code register */
  53. GBL= 0x20,
  54. BO= 0x18,
  55. EB= 0x10, /* Motorola byte order */
  56. TC2= 0x04,
  57. DTB= 0x02,
  58. BDB= 0x01,
  59. /* FCC Event/Mask bits */
  60. GRA= SBIT(8),
  61. RXC= SBIT(9),
  62. TXC= SBIT(10),
  63. TXE= SBIT(11),
  64. RXF= SBIT(12),
  65. BSY= SBIT(13),
  66. TXB= SBIT(14),
  67. RXB= SBIT(15),
  68. };
  69. enum { /* Mcr */
  70. MDIread = 0x60020000, /* read opcode */
  71. MDIwrite = 0x50020000, /* write opcode */
  72. };
  73. typedef struct Etherparam Etherparam;
  74. struct Etherparam {
  75. /*0x00*/ FCCparam;
  76. /*0x3c*/ ulong stat_buf;
  77. /*0x40*/ ulong cam_ptr;
  78. /*0x44*/ ulong cmask;
  79. /*0x48*/ ulong cpres;
  80. /*0x4c*/ ulong crcec;
  81. /*0x50*/ ulong alec;
  82. /*0x54*/ ulong disfc;
  83. /*0x58*/ ushort retlim;
  84. /*0x5a*/ ushort retcnt;
  85. /*0x5c*/ ushort p_per;
  86. /*0x5e*/ ushort boff_cnt;
  87. /*0x60*/ ulong gaddr[2];
  88. /*0x68*/ ushort tfcstat;
  89. /*0x6a*/ ushort tfclen;
  90. /*0x6c*/ ulong tfcptr;
  91. /*0x70*/ ushort mflr;
  92. /*0x72*/ ushort paddr[3];
  93. /*0x78*/ ushort ibd_cnt;
  94. /*0x7a*/ ushort ibd_start;
  95. /*0x7c*/ ushort ibd_end;
  96. /*0x7e*/ ushort tx_len;
  97. /*0x80*/ uchar ibd_base[32];
  98. /*0xa0*/ ulong iaddr[2];
  99. /*0xa8*/ ushort minflr;
  100. /*0xaa*/ ushort taddr[3];
  101. /*0xb0*/ ushort padptr;
  102. /*0xb2*/ ushort Rsvdb2;
  103. /*0xb4*/ ushort cf_range;
  104. /*0xb6*/ ushort max_b;
  105. /*0xb8*/ ushort maxd1;
  106. /*0xba*/ ushort maxd2;
  107. /*0xbc*/ ushort maxd;
  108. /*0xbe*/ ushort dma_cnt;
  109. /*0xc0*/ ulong octc;
  110. /*0xc4*/ ulong colc;
  111. /*0xc8*/ ulong broc;
  112. /*0xcc*/ ulong mulc;
  113. /*0xd0*/ ulong uspc;
  114. /*0xd4*/ ulong frgc;
  115. /*0xd8*/ ulong ospc;
  116. /*0xdc*/ ulong jbrc;
  117. /*0xe0*/ ulong p64c;
  118. /*0xe4*/ ulong p65c;
  119. /*0xe8*/ ulong p128c;
  120. /*0xec*/ ulong p256c;
  121. /*0xf0*/ ulong p512c;
  122. /*0xf4*/ ulong p1024c;
  123. /*0xf8*/ ulong cam_buf;
  124. /*0xfc*/ ulong Rsvdfc;
  125. /*0x100*/
  126. };
  127. typedef struct Ctlr Ctlr;
  128. struct Ctlr {
  129. Lock;
  130. int fccid;
  131. int port;
  132. ulong pmdio;
  133. ulong pmdck;
  134. int init;
  135. int active;
  136. int duplex; /* 1 == full */
  137. FCC* fcc;
  138. Ring;
  139. Block* rcvbufs[Nrdre];
  140. Mii* mii;
  141. Timer;
  142. ulong interrupts; /* statistics */
  143. ulong deferred;
  144. ulong heartbeat;
  145. ulong latecoll;
  146. ulong retrylim;
  147. ulong underrun;
  148. ulong overrun;
  149. ulong carrierlost;
  150. ulong retrycount;
  151. };
  152. static int fccirq[] = {0x20, 0x21, 0x22};
  153. static int fccid[] = {FCC1ID, FCC2ID, FCC3ID};
  154. #ifdef DBG
  155. ulong fccrhisto[16];
  156. ulong fccthisto[16];
  157. ulong fccrthisto[16];
  158. ulong fcctrhisto[16];
  159. ulong ehisto[0x80];
  160. #endif
  161. static int fccmiimir(Mii*, int, int);
  162. static int fccmiimiw(Mii*, int, int, int);
  163. static void fccltimer(Ureg*, Timer*);
  164. static void
  165. attach(Ether *ether)
  166. {
  167. Ctlr *ctlr;
  168. ctlr = ether->ctlr;
  169. ilock(ctlr);
  170. ctlr->active = 1;
  171. ctlr->fcc->gfmr |= ENR|ENT;
  172. iunlock(ctlr);
  173. ctlr->tmode = Tperiodic;
  174. ctlr->tf = fccltimer;
  175. ctlr->ta = ether;
  176. ctlr->tns = 5000000000LL; /* 5 seconds */
  177. timeradd(ctlr);
  178. }
  179. static void
  180. closed(Ether *ether)
  181. {
  182. Ctlr *ctlr;
  183. ctlr = ether->ctlr;
  184. ilock(ctlr);
  185. ctlr->active = 0;
  186. ctlr->fcc->gfmr &= ~(ENR|ENT);
  187. iunlock(ctlr);
  188. print("Ether closed\n");
  189. }
  190. static void
  191. promiscuous(void* arg, int on)
  192. {
  193. Ether *ether;
  194. Ctlr *ctlr;
  195. ether = (Ether*)arg;
  196. ctlr = ether->ctlr;
  197. ilock(ctlr);
  198. if(on || ether->nmaddr)
  199. ctlr->fcc->fpsmr |= PRO;
  200. else
  201. ctlr->fcc->fpsmr &= ~PRO;
  202. iunlock(ctlr);
  203. }
  204. static void
  205. multicast(void* arg, uchar *addr, int on)
  206. {
  207. Ether *ether;
  208. Ctlr *ctlr;
  209. USED(addr, on); /* if on, could SetGroupAddress; if !on, it's hard */
  210. ether = (Ether*)arg;
  211. ctlr = ether->ctlr;
  212. ilock(ctlr);
  213. if(ether->prom || ether->nmaddr)
  214. ctlr->fcc->fpsmr |= PRO;
  215. else
  216. ctlr->fcc->fpsmr &= ~PRO;
  217. iunlock(ctlr);
  218. }
  219. static void
  220. txstart(Ether *ether)
  221. {
  222. int len;
  223. Ctlr *ctlr;
  224. Block *b;
  225. BD *dre;
  226. ctlr = ether->ctlr;
  227. if(ctlr->init)
  228. return;
  229. while(ctlr->ntq < Ntdre-1){
  230. b = qget(ether->oq);
  231. if(b == 0)
  232. break;
  233. dre = &ctlr->tdr[ctlr->tdrh];
  234. dczap(dre, sizeof(BD));
  235. if(dre->status & BDReady)
  236. panic("ether: txstart");
  237. /*
  238. * Give ownership of the descriptor to the chip, increment the
  239. * software ring descriptor pointer and tell the chip to poll.
  240. */
  241. len = BLEN(b);
  242. if(ctlr->txb[ctlr->tdrh] != nil)
  243. panic("fcc/ether: txstart");
  244. ctlr->txb[ctlr->tdrh] = b;
  245. if((ulong)b->rp&1)
  246. panic("fcc/ether: txstart align"); /* TO DO: ensure alignment */
  247. dre->addr = PADDR(b->rp);
  248. dre->length = len;
  249. dcflush(b->rp, len);
  250. dcflush(dre, sizeof(BD));
  251. dre->status = (dre->status & BDWrap) | BDReady|TxPad|BDInt|BDLast|TxTC;
  252. dcflush(dre, sizeof(BD));
  253. /* ctlr->fcc->ftodr = 1<<15; /* transmit now; Don't do this according to errata */
  254. ctlr->ntq++;
  255. ctlr->tdrh = NEXT(ctlr->tdrh, Ntdre);
  256. }
  257. }
  258. static void
  259. transmit(Ether* ether)
  260. {
  261. Ctlr *ctlr;
  262. ctlr = ether->ctlr;
  263. ilock(ctlr);
  264. txstart(ether);
  265. iunlock(ctlr);
  266. }
  267. static void
  268. interrupt(Ureg*, void *arg)
  269. {
  270. int len, status, rcvd, xmtd, restart;
  271. ushort events;
  272. Ctlr *ctlr;
  273. BD *dre;
  274. Block *b, *nb;
  275. Ether *ether = arg;
  276. ctlr = ether->ctlr;
  277. if(!ctlr->active)
  278. return; /* not ours */
  279. /*
  280. * Acknowledge all interrupts and whine about those that shouldn't
  281. * happen.
  282. */
  283. events = ctlr->fcc->fcce;
  284. ctlr->fcc->fcce = events; /* clear events */
  285. #ifdef DBG
  286. ehisto[events & 0x7f]++;
  287. #endif
  288. ctlr->interrupts++;
  289. if(events & BSY)
  290. ctlr->overrun++;
  291. if(events & TXE)
  292. ether->oerrs++;
  293. #ifdef DBG
  294. rcvd = xmtd = 0;
  295. #endif
  296. /*
  297. * Receiver interrupt: run round the descriptor ring logging
  298. * errors and passing valid receive data up to the higher levels
  299. * until we encounter a descriptor still owned by the chip.
  300. */
  301. if(events & RXF){
  302. dre = &ctlr->rdr[ctlr->rdrx];
  303. dczap(dre, sizeof(BD));
  304. while(((status = dre->status) & BDEmpty) == 0){
  305. rcvd++;
  306. if(status & RxError || (status & (BDFirst|BDLast)) != (BDFirst|BDLast)){
  307. if(status & (RxeLG|RxeSH))
  308. ether->buffs++;
  309. if(status & RxeNO)
  310. ether->frames++;
  311. if(status & RxeCR)
  312. ether->crcs++;
  313. if(status & RxeOV)
  314. ether->overflows++;
  315. print("eth rx: %ux\n", status);
  316. }else{
  317. /*
  318. * We have a packet. Read it in.
  319. */
  320. len = dre->length-4;
  321. b = ctlr->rcvbufs[ctlr->rdrx];
  322. assert(dre->addr == PADDR(b->rp));
  323. dczap(b->rp, len);
  324. if(nb = iallocb(Bufsize)){
  325. b->wp += len;
  326. etheriq(ether, b, 1);
  327. b = nb;
  328. b->rp = (uchar*)(((ulong)b->rp + CACHELINESZ-1) & ~(CACHELINESZ-1));
  329. b->wp = b->rp;
  330. ctlr->rcvbufs[ctlr->rdrx] = b;
  331. ctlr->rdr[ctlr->rdrx].addr = PADDR(b->wp);
  332. }else
  333. ether->soverflows++;
  334. }
  335. /*
  336. * Finished with this descriptor, reinitialise it,
  337. * give it back to the chip, then on to the next...
  338. */
  339. dre->length = 0;
  340. dre->status = (status & BDWrap) | BDEmpty | BDInt;
  341. dcflush(dre, sizeof(BD));
  342. ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre);
  343. dre = &ctlr->rdr[ctlr->rdrx];
  344. dczap(dre, sizeof(BD));
  345. }
  346. }
  347. /*
  348. * Transmitter interrupt: handle anything queued for a free descriptor.
  349. */
  350. if(events & (TXB|TXE)){
  351. ilock(ctlr);
  352. restart = 0;
  353. while(ctlr->ntq){
  354. dre = &ctlr->tdr[ctlr->tdri];
  355. dczap(dre, sizeof(BD));
  356. status = dre->status;
  357. if(status & BDReady)
  358. break;
  359. if(status & TxeDEF)
  360. ctlr->deferred++;
  361. if(status & TxeHB)
  362. ctlr->heartbeat++;
  363. if(status & TxeLC)
  364. ctlr->latecoll++;
  365. if(status & TxeRL)
  366. ctlr->retrylim++;
  367. if(status & TxeUN)
  368. ctlr->underrun++;
  369. if(status & TxeCSL)
  370. ctlr->carrierlost++;
  371. if(status & (TxeLC|TxeRL|TxeUN))
  372. restart = 1;
  373. ctlr->retrycount += (status>>2)&0xF;
  374. b = ctlr->txb[ctlr->tdri];
  375. if(b == nil)
  376. panic("fcce/interrupt: bufp");
  377. ctlr->txb[ctlr->tdri] = nil;
  378. freeb(b);
  379. ctlr->ntq--;
  380. ctlr->tdri = NEXT(ctlr->tdri, Ntdre);
  381. xmtd++;
  382. }
  383. if(restart){
  384. ctlr->fcc->gfmr &= ~ENT;
  385. delay(10);
  386. ctlr->fcc->gfmr |= ENT;
  387. cpmop(RestartTx, ctlr->fccid, 0xc);
  388. }
  389. txstart(ether);
  390. iunlock(ctlr);
  391. }
  392. #ifdef DBG
  393. if(rcvd >= nelem(fccrhisto))
  394. rcvd = nelem(fccrhisto) - 1;
  395. if(xmtd >= nelem(fccthisto))
  396. xmtd = nelem(fccthisto) - 1;
  397. if(rcvd)
  398. fcctrhisto[xmtd]++;
  399. else
  400. fccthisto[xmtd]++;
  401. if(xmtd)
  402. fccrthisto[rcvd]++;
  403. else
  404. fccrhisto[rcvd]++;
  405. #endif
  406. }
  407. static long
  408. ifstat(Ether* ether, void* a, long n, ulong offset)
  409. {
  410. char *p;
  411. int len, i, r;
  412. Ctlr *ctlr;
  413. MiiPhy *phy;
  414. if(n == 0)
  415. return 0;
  416. ctlr = ether->ctlr;
  417. p = malloc(2*READSTR);
  418. len = snprint(p, 2*READSTR, "interrupts: %lud\n", ctlr->interrupts);
  419. len += snprint(p+len, 2*READSTR-len, "carrierlost: %lud\n", ctlr->carrierlost);
  420. len += snprint(p+len, 2*READSTR-len, "heartbeat: %lud\n", ctlr->heartbeat);
  421. len += snprint(p+len, 2*READSTR-len, "retrylimit: %lud\n", ctlr->retrylim);
  422. len += snprint(p+len, 2*READSTR-len, "retrycount: %lud\n", ctlr->retrycount);
  423. len += snprint(p+len, 2*READSTR-len, "latecollisions: %lud\n", ctlr->latecoll);
  424. len += snprint(p+len, 2*READSTR-len, "rxoverruns: %lud\n", ctlr->overrun);
  425. len += snprint(p+len, 2*READSTR-len, "txunderruns: %lud\n", ctlr->underrun);
  426. len += snprint(p+len, 2*READSTR-len, "framesdeferred: %lud\n", ctlr->deferred);
  427. miistatus(ctlr->mii);
  428. phy = ctlr->mii->curphy;
  429. len += snprint(p+len, 2*READSTR-len, "phy: link=%d, tfc=%d, rfc=%d, speed=%d, fd=%d\n",
  430. phy->link, phy->tfc, phy->rfc, phy->speed, phy->fd);
  431. #ifdef DBG
  432. if(ctlr->mii != nil && ctlr->mii->curphy != nil){
  433. len += snprint(p+len, 2*READSTR, "phy: ");
  434. for(i = 0; i < NMiiPhyr; i++){
  435. if(i && ((i & 0x07) == 0))
  436. len += snprint(p+len, 2*READSTR-len, "\n ");
  437. r = miimir(ctlr->mii, i);
  438. len += snprint(p+len, 2*READSTR-len, " %4.4uX", r);
  439. }
  440. snprint(p+len, 2*READSTR-len, "\n");
  441. }
  442. #endif
  443. snprint(p+len, 2*READSTR-len, "\n");
  444. n = readstr(offset, a, n, p);
  445. free(p);
  446. return n;
  447. }
  448. /*
  449. * This follows the MPC8260 user guide: section28.9's initialisation sequence.
  450. */
  451. static int
  452. fccsetup(Ctlr *ctlr, FCC *fcc, uchar *ea)
  453. {
  454. int i;
  455. Etherparam *p;
  456. MiiPhy *phy;
  457. /* Turn Ethernet off */
  458. fcc->gfmr &= ~(ENR | ENT);
  459. ioplock();
  460. switch(ctlr->port) {
  461. default:
  462. iopunlock();
  463. return -1;
  464. case 0:
  465. /* Step 1 (Section 28.9), write the parallel ports */
  466. ctlr->pmdio = 0x01000000;
  467. ctlr->pmdck = 0x08000000;
  468. imm->port[0].pdir &= ~A1dir0;
  469. imm->port[0].pdir |= A1dir1;
  470. imm->port[0].psor &= ~A1psor0;
  471. imm->port[0].psor |= A1psor1;
  472. imm->port[0].ppar |= (A1dir0 | A1dir1);
  473. /* Step 2, Port C clocks */
  474. imm->port[2].psor &= ~0x00000c00;
  475. imm->port[2].pdir &= ~0x00000c00;
  476. imm->port[2].ppar |= 0x00000c00;
  477. imm->port[3].pdat |= (ctlr->pmdio | ctlr->pmdck);
  478. imm->port[3].podr |= ctlr->pmdio;
  479. imm->port[3].pdir |= (ctlr->pmdio | ctlr->pmdck);
  480. imm->port[3].ppar &= ~(ctlr->pmdio | ctlr->pmdck);
  481. eieio();
  482. /* Step 3, Serial Interface clock routing */
  483. imm->cmxfcr &= ~0xff000000; /* Clock mask */
  484. imm->cmxfcr |= 0x37000000; /* Clock route */
  485. break;
  486. case 1:
  487. /* Step 1 (Section 28.9), write the parallel ports */
  488. ctlr->pmdio = 0x00400000;
  489. ctlr->pmdck = 0x00200000;
  490. imm->port[1].pdir &= ~B2dir0;
  491. imm->port[1].pdir |= B2dir1;
  492. imm->port[1].psor &= ~B2psor0;
  493. imm->port[1].psor |= B2psor1;
  494. imm->port[1].ppar |= (B2dir0 | B2dir1);
  495. /* Step 2, Port C clocks */
  496. imm->port[2].psor &= ~0x00003000;
  497. imm->port[2].pdir &= ~0x00003000;
  498. imm->port[2].ppar |= 0x00003000;
  499. imm->port[2].pdat |= (ctlr->pmdio | ctlr->pmdck);
  500. imm->port[2].podr |= ctlr->pmdio;
  501. imm->port[2].pdir |= (ctlr->pmdio | ctlr->pmdck);
  502. imm->port[2].ppar &= ~(ctlr->pmdio | ctlr->pmdck);
  503. eieio();
  504. /* Step 3, Serial Interface clock routing */
  505. imm->cmxfcr &= ~0x00ff0000;
  506. imm->cmxfcr |= 0x00250000;
  507. break;
  508. case 2:
  509. /* Step 1 (Section 28.9), write the parallel ports */
  510. imm->port[1].pdir &= ~B3dir0;
  511. imm->port[1].pdir |= B3dir1;
  512. imm->port[1].psor &= ~B3psor0;
  513. imm->port[1].psor |= B3psor1;
  514. imm->port[1].ppar |= (B3dir0 | B3dir1);
  515. /* Step 2, Port C clocks */
  516. imm->port[2].psor &= ~0x0000c000;
  517. imm->port[2].pdir &= ~0x0000c000;
  518. imm->port[2].ppar |= 0x0000c000;
  519. imm->port[3].pdat |= (ctlr->pmdio | ctlr->pmdck);
  520. imm->port[3].podr |= ctlr->pmdio;
  521. imm->port[3].pdir |= (ctlr->pmdio | ctlr->pmdck);
  522. imm->port[3].ppar &= ~(ctlr->pmdio | ctlr->pmdck);
  523. eieio();
  524. /* Step 3, Serial Interface clock routing */
  525. imm->cmxfcr &= ~0x0000ff00;
  526. imm->cmxfcr |= 0x00003700;
  527. break;
  528. }
  529. iopunlock();
  530. p = (Etherparam*)(m->immr->prmfcc + ctlr->port);
  531. memset(p, 0, sizeof(Etherparam));
  532. /* Step 4 */
  533. fcc->gfmr |= ENET;
  534. /* Step 5 */
  535. fcc->fpsmr = CRCE | FDE | LPB; /* full duplex operation */
  536. ctlr->duplex = ~0;
  537. /* Step 6 */
  538. fcc->fdsr = 0xd555;
  539. /* Step 7, initialize parameter ram */
  540. p->rbase = PADDR(ctlr->rdr);
  541. p->tbase = PADDR(ctlr->tdr);
  542. p->rstate = (GBL | EB) << 24;
  543. p->tstate = (GBL | EB) << 24;
  544. p->cmask = 0xdebb20e3;
  545. p->cpres = 0xffffffff;
  546. p->retlim = 15; /* retry limit */
  547. p->mrblr = (Rbsize+0x1f)&~0x1f; /* multiple of 32 */
  548. p->mflr = Rbsize;
  549. p->minflr = ETHERMINTU;
  550. p->maxd1 = (Rbsize+7) & ~7;
  551. p->maxd2 = (Rbsize+7) & ~7;
  552. for(i=0; i<Eaddrlen; i+=2)
  553. p->paddr[2-i/2] = (ea[i+1]<<8)|ea[i];
  554. /* Step 7, initialize parameter ram, configuration-dependent values */
  555. p->riptr = m->immr->fccextra[ctlr->port].ri - (uchar*)IMMR;
  556. p->tiptr = m->immr->fccextra[ctlr->port].ti - (uchar*)IMMR;
  557. p->padptr = m->immr->fccextra[ctlr->port].pad - (uchar*)IMMR;
  558. memset(m->immr->fccextra[ctlr->port].pad, 0x88, 0x20);
  559. /* Step 8, clear out events */
  560. fcc->fcce = ~0;
  561. /* Step 9, Interrupt enable */
  562. fcc->fccm = TXE | RXF | TXB;
  563. /* Step 10, Configure interrupt priority (not done here) */
  564. /* Step 11, Clear out current events */
  565. /* Step 12, Enable interrupts to the CP interrupt controller */
  566. /* Step 13, Issue the Init Tx and Rx command, specifying 0xc for ethernet*/
  567. cpmop(InitRxTx, fccid[ctlr->port], 0xc);
  568. /* Step 14, Link management */
  569. if((ctlr->mii = malloc(sizeof(Mii))) == nil)
  570. return -1;
  571. ctlr->mii->mir = fccmiimir;
  572. ctlr->mii->miw = fccmiimiw;
  573. ctlr->mii->ctlr = ctlr;
  574. if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){
  575. free(ctlr->mii);
  576. ctlr->mii = nil;
  577. return -1;
  578. }
  579. miiane(ctlr->mii, ~0, ~0, ~0);
  580. #ifdef DBG
  581. print("oui=%X, phyno=%d, ", phy->oui, phy->phyno);
  582. print("anar=%ux, ", phy->anar);
  583. print("fc=%ux, ", phy->fc);
  584. print("mscr=%ux, ", phy->mscr);
  585. print("link=%ux, ", phy->link);
  586. print("speed=%ux, ", phy->speed);
  587. print("fd=%ux, ", phy->fd);
  588. print("rfc=%ux, ", phy->rfc);
  589. print("tfc=%ux\n", phy->tfc);
  590. #endif
  591. /* Step 15, Enable ethernet: done at attach time */
  592. return 0;
  593. }
  594. static int
  595. reset(Ether* ether)
  596. {
  597. uchar ea[Eaddrlen];
  598. Ctlr *ctlr;
  599. FCC *fcc;
  600. Block *b;
  601. int i;
  602. if(m->cpuhz < 24000000){
  603. print("%s ether: system speed must be >= 24MHz for ether use\n", ether->type);
  604. return -1;
  605. }
  606. if(ether->port > 3){
  607. print("%s ether: no FCC port %ld\n", ether->type, ether->port);
  608. return -1;
  609. }
  610. ether->irq = fccirq[ether->port];
  611. ether->tbdf = BusPPC;
  612. fcc = imm->fcc + ether->port;
  613. ctlr = malloc(sizeof(*ctlr));
  614. ether->ctlr = ctlr;
  615. memset(ctlr, 0, sizeof(*ctlr));
  616. ctlr->fcc = fcc;
  617. ctlr->port = ether->port;
  618. ctlr->fccid = fccid[ether->port];
  619. /* Ioringinit will allocate the buffer descriptors in normal memory
  620. * and NOT in Dual-Ported Ram, as prescribed by the MPC8260
  621. * PowerQUICC II manual (Section 28.6). When they are allocated
  622. * in DPram and the Dcache is enabled, the processor will hang
  623. */
  624. if(ioringinit(ctlr, Nrdre, Ntdre, 0) < 0)
  625. panic("etherfcc init");
  626. for(i = 0; i < Nrdre; i++){
  627. b = iallocb(Bufsize);
  628. b->rp = (uchar*)(((ulong)b->rp + CACHELINESZ-1) & ~(CACHELINESZ-1));
  629. b->wp = b->rp;
  630. ctlr->rcvbufs[i] = b;
  631. ctlr->rdr[i].addr = PADDR(b->wp);
  632. }
  633. fccsetup(ctlr, fcc, ether->ea);
  634. ether->mbps = 100; /* TO DO: could be 10mbps */
  635. ether->attach = attach;
  636. ether->transmit = transmit;
  637. ether->interrupt = interrupt;
  638. ether->ifstat = ifstat;
  639. ether->arg = ether;
  640. ether->promiscuous = promiscuous;
  641. ether->multicast = multicast;
  642. /*
  643. * Until we know where to find it, insist that the plan9.ini
  644. * entry holds the Ethernet address.
  645. */
  646. memset(ea, 0, Eaddrlen);
  647. if(memcmp(ea, ether->ea, Eaddrlen) == 0){
  648. print("no ether address");
  649. return -1;
  650. }
  651. return 0;
  652. }
  653. void
  654. etherfcclink(void)
  655. {
  656. addethercard("fcc", reset);
  657. }
  658. static void
  659. nanodelay(void)
  660. {
  661. static int count;
  662. int i;
  663. for(i = 0; i < 500; i++)
  664. count++;
  665. return;
  666. }
  667. static
  668. void miiwriteloop(Ctlr *ctlr, Port *port, int cnt, ulong cmd)
  669. {
  670. int i;
  671. for(i = 0; i < cnt; i++){
  672. port->pdat &= ~ctlr->pmdck;
  673. if(cmd & BIT(i))
  674. port->pdat |= ctlr->pmdio;
  675. else
  676. port->pdat &= ~ctlr->pmdio;
  677. nanodelay();
  678. port->pdat |= ctlr->pmdck;
  679. nanodelay();
  680. }
  681. }
  682. static int
  683. fccmiimiw(Mii *mii, int pa, int ra, int data)
  684. {
  685. int x;
  686. Port *port;
  687. ulong cmd;
  688. Ctlr *ctlr;
  689. /*
  690. * MII Management Interface Write.
  691. */
  692. ctlr = mii->ctlr;
  693. port = imm->port + 3;
  694. cmd = MDIwrite | (pa<<(5+2+16))| (ra<<(2+16)) | (data & 0xffff);
  695. x = splhi();
  696. port->pdir |= (ctlr->pmdio|ctlr->pmdck);
  697. nanodelay();
  698. miiwriteloop(ctlr, port, 32, ~0);
  699. miiwriteloop(ctlr, port, 32, cmd);
  700. port->pdir |= (ctlr->pmdio|ctlr->pmdck);
  701. nanodelay();
  702. miiwriteloop(ctlr, port, 32, ~0);
  703. splx(x);
  704. return 1;
  705. }
  706. static int
  707. fccmiimir(Mii *mii, int pa, int ra)
  708. {
  709. int data, i, x;
  710. Port *port;
  711. ulong cmd;
  712. Ctlr *ctlr;
  713. ctlr = mii->ctlr;
  714. port = imm->port + 3;
  715. cmd = MDIread | pa<<(5+2+16) | ra<<(2+16);
  716. x = splhi();
  717. port->pdir |= (ctlr->pmdio|ctlr->pmdck);
  718. nanodelay();
  719. miiwriteloop(ctlr, port, 32, ~0);
  720. /* Clock out the first 14 MS bits of the command */
  721. miiwriteloop(ctlr, port, 14, cmd);
  722. /* Turn-around */
  723. port->pdat &= ~ctlr->pmdck;
  724. port->pdir &= ~ctlr->pmdio;
  725. nanodelay();
  726. /* For read, clock in 18 bits, use 16 */
  727. data = 0;
  728. for(i=0; i<18; i++){
  729. data <<= 1;
  730. if(port->pdat & ctlr->pmdio)
  731. data |= 1;
  732. port->pdat |= ctlr->pmdck;
  733. nanodelay();
  734. port->pdat &= ~ctlr->pmdck;
  735. nanodelay();
  736. }
  737. port->pdir |= (ctlr->pmdio|ctlr->pmdck);
  738. nanodelay();
  739. miiwriteloop(ctlr, port, 32, ~0);
  740. splx(x);
  741. return data & 0xffff;
  742. }
  743. static void
  744. fccltimer(Ureg*, Timer *t)
  745. {
  746. Ether *ether;
  747. Ctlr *ctlr;
  748. MiiPhy *phy;
  749. ulong gfmr;
  750. ether = t->ta;
  751. ctlr = ether->ctlr;
  752. if(ctlr->mii == nil || ctlr->mii->curphy == nil)
  753. return;
  754. phy = ctlr->mii->curphy;
  755. if(miistatus(ctlr->mii) < 0){
  756. print("miistatus failed\n");
  757. return;
  758. }
  759. if(phy->link == 0){
  760. print("link lost\n");
  761. return;
  762. }
  763. ether->mbps = phy->speed;
  764. if(phy->fd != ctlr->duplex)
  765. print("set duplex\n");
  766. ilock(ctlr);
  767. gfmr = ctlr->fcc->gfmr;
  768. if(phy->fd != ctlr->duplex){
  769. ctlr->fcc->gfmr &= ~(ENR|ENT);
  770. if(phy->fd)
  771. ctlr->fcc->fpsmr |= FDE | LPB; /* full duplex operation */
  772. else
  773. ctlr->fcc->fpsmr &= ~(FDE | LPB); /* half duplex operation */
  774. ctlr->duplex = phy->fd;
  775. }
  776. ctlr->fcc->gfmr = gfmr;
  777. iunlock(ctlr);
  778. }