2 #include "../port/lib.h"
7 #include "../port/netif.h"
8 #include "../port/etherif.h"
10 #define Rbsz ROUNDUP(sizeof(Etherpkt)+16, 64)
100 GEM0_CLK_CTRL = 0x140/4,
103 typedef struct Ctlr Ctlr;
109 int rxconsi, rxprodi, txi;
119 return ((Ctlr*)v)->r[NET_STATUS] & PHY_IDLE;
123 mdwrite(Ctlr *c, int r, u16int v)
125 sleep(&c->phy, phyidle, c);
126 c->r[PHY_MAINT] = 1<<30 | 1<<28 | 1<<17 | c->phyaddr << 23 | r << 18 | v;
127 sleep(&c->phy, phyidle, c);
131 mdread(Ctlr *c, int r)
133 sleep(&c->phy, phyidle, c);
134 c->r[PHY_MAINT] = 1<<30 | 1<< 29 | 1<<17 | c->phyaddr << 23 | r << 18;
135 sleep(&c->phy, phyidle, c);
136 return c->r[PHY_MAINT];
149 mdwrite(c, MDCTRL, AUTONEG);
151 if((mdread(c, MDSTATUS) & LINK) == 0){
153 print("eth: no link\n");
154 while((mdread(c, MDSTATUS) & LINK) == 0)
155 tsleep(&up->sleep, return0, nil, Linkdelay);
157 v = mdread(c, MDPHYCTRL);
160 while((mdread(c, MDGSTATUS) & RECVOK) != RECVOK)
163 c->r[NET_CFG] |= GIGE_EN;
164 slcr[GEM0_CLK_CTRL] = 1 << 20 | 8 << 8 | 1;
165 }else if((v & 0x20) != 0){
168 c->r[NET_CFG] = c->r[NET_CFG] & ~GIGE_EN | SPEED;
169 slcr[GEM0_CLK_CTRL] = 5 << 20 | 8 << 8 | 1;
170 }else if((v & 0x10) != 0){
173 c->r[NET_CFG] = c->r[NET_CFG] & ~(GIGE_EN | SPEED);
174 slcr[GEM0_CLK_CTRL] = 20 << 20 | 20 << 8 | 1;
179 c->r[NET_CFG] |= FDEN;
182 c->r[NET_CFG] &= ~FDEN;
185 print("eth: %s %s duplex link\n", sp, dpl);
186 while((mdread(c, MDSTATUS) & LINK) != 0)
187 tsleep(&up->sleep, return0, nil, Linkdelay);
198 while(c->rxprodi != c->rxconsi){
202 print("eth: out of memory for receive buffers\n");
207 r[0] = RxUsed | PADDR(bp->rp);
211 cleandse(bp->base, bp->lim);
212 clean2pa(PADDR(bp->base), PADDR(bp->lim));
214 c->rxprodi = (c->rxprodi + 1) & (RXRING - 1);
227 // print("rx! %p %p\n", PADDR(&c->rxr[2 * c->rxconsi]), c->r[RX_QBAR]);
229 r = &c->rxr[2 * c->rxconsi];
230 if((r[0] & RxUsed) == 0)
232 if((r[1] & FrameEnd) == 0)
233 print("eth: partial frame received -- shouldn't happen\n");
234 bp = c->rxs[c->rxconsi];
235 bp->wp = bp->rp + (r[1] & 0x1fff);
236 invaldse(bp->rp, bp->wp);
237 inval2pa(PADDR(bp->rp), PADDR(bp->wp));
239 c->rxconsi = (c->rxconsi + 1) & (RXRING - 1);
254 r = &c->txr[2 * c->txi];
255 if((r[1] & TxUsed) == 0){
256 print("eth: transmit buffer full\n");
262 if(c->txs[c->txi] != nil)
263 freeb(c->txs[c->txi]);
265 cleandse(bp->rp, bp->wp);
266 clean2pa(PADDR(bp->rp), PADDR(bp->wp));
267 r[0] = PADDR(bp->rp);
268 r[1] = BLEN(bp) | FrameEnd | TxUsed;
269 if(r == c->txr + 2 * (TXRING - 1))
274 c->r[NET_CTRL] |= STARTTX;
275 c->txi = (c->txi + 1) & (TXRING - 1);
281 ethirq(Ureg *, void *arg)
289 fl = c->r[INTR_STATUS];
290 c->r[INTR_STATUS] = fl;
291 if((fl & MGMTDONE) != 0)
293 if((fl & TXUNDER) != 0)
295 if((fl & RXCOMPL) != 0)
297 if((fl & RXUSED) != 0)
298 print("eth: DMA read RX descriptor with used bit set, shouldn't happen\n");
299 if((fl & RXOVER) != 0)
300 print("eth: RX overrun, shouldn't happen\n");
304 ethprom(void *arg, int on)
312 c->r[NET_CFG] |= COPYALLEN;
314 c->r[NET_CFG] &= ~COPYALLEN;
318 ethmcast(void *arg, uchar *ea, int on)
327 if(edev->nmaddr == 0){
328 c->r[NET_CFG] &= ~MCASTHASHEN;
334 a = (u64int)ea[0] | (u64int)ea[1]<<8 | (u64int)ea[2]<<16 |
335 (u64int)ea[3]<<24 | (u64int)ea[4]<<32 | (u64int)ea[5]<<40;
336 x = a ^ (a>>6) ^ (a>>12) ^ (a>>18) ^ (a>>24) ^ (a>>30) ^ (a>>36) ^ (a>>42);
339 c->r[HASH_BOT] |= 1<<x;
341 c->r[HASH_TOP] |= 1<<(x-32);
342 c->r[NET_CFG] |= MCASTHASHEN;
353 c->r[RX_STATUS] = 0xf;
354 c->r[TX_STATUS] = 0xff;
355 c->r[INTR_DIS] = 0x7FFFEFF;
356 c->r[NET_CFG] = MDC_DIV << 18 | FDEN | SPEED | RX1536EN | GIGE_EN | RXCHKSUMEN;
357 c->r[SPEC_ADDR1_BOT] = edev->ea[0] | edev->ea[1] << 8 | edev->ea[2] << 16 | edev->ea[3] << 24;
358 c->r[SPEC_ADDR1_TOP] = edev->ea[4] | edev->ea[5] << 8;
359 c->r[DMA_CFG] = TXCHKSUMEN | (Rbsz/64) << 16 | 1 << 10 | 3 << 8 | 0x10;
361 c->rxr = ucalloc(8 * RXRING);
362 c->txr = ucalloc(8 * TXRING);
363 c->rxs = xspanalloc(4 * RXRING, 4, 0);
364 c->txs = xspanalloc(4 * TXRING, 4, 0);
365 for(i = 0; i < 2 * RXRING; ){
373 for(i = 0; i < 2 * TXRING; ){
377 c->txr[2 * (TXRING - 1)] |= 1<<30;
378 c->r[RX_QBAR] = PADDR(c->rxr);
379 c->r[TX_QBAR] = PADDR(c->txr);
381 c->r[NET_CTRL] = MDEN | TXEN | RXEN;
382 c->r[INTR_EN] = MGMTDONE | TXUNDER | RXCOMPL | RXUSED | RXOVER;
387 ethattach(Ether *edev)
395 kproc("ethproc", ethproc, edev);
399 etherpnp(Ether *edev)
402 static uchar mac[] = {0x0e, 0xa7, 0xde, 0xad, 0xbe, 0xef};
407 memmove(edev->ea, mac, 6);
409 edev->port = ETH0_BASE;
410 ct.r = vmap(edev->port, BY2PG);
413 edev->transmit = ethtx;
414 edev->attach = ethattach;
415 edev->promiscuous = ethprom;
416 edev->multicast = ethmcast;
420 if(ethinit(edev) < 0){
425 intrenable(edev->irq, ethirq, edev, LEVEL, edev->name);
432 addethercard("eth", etherpnp);