📄 greth.c
字号:
(dev->gb << 8) | (dev->sp << 7) | (dev->fd << 4)); return 0;}void greth_halt(struct eth_device *dev){ greth_priv *greth; greth_regs *regs; int i;#ifdef DEBUG printf("greth_halt\n");#endif if (!dev || !dev->priv) return; greth = dev->priv; regs = greth->regs; if (!regs) return; /* disable receiver/transmitter by clearing the enable bits */ GRETH_REGANDIN(®s->control, ~(GRETH_RXEN | GRETH_TXEN)); /* reset rx/tx descriptors */ if (greth->rxbd_base) { for (i = 0; i < GRETH_RXBD_CNT; i++) { greth->rxbd_base[i].stat = (i >= (GRETH_RXBD_CNT - 1)) ? GRETH_BD_WR : 0; } } if (greth->txbd_base) { for (i = 0; i < GRETH_TXBD_CNT; i++) { greth->txbd_base[i].stat = (i >= (GRETH_TXBD_CNT - 1)) ? GRETH_BD_WR : 0; } }}int greth_send(struct eth_device *dev, volatile void *eth_data, int data_length){ greth_priv *greth = dev->priv; greth_regs *regs = greth->regs; greth_bd *txbd; void *txbuf; unsigned int status;#ifdef DEBUG printf("greth_send\n");#endif /* send data, wait for data to be sent, then return */ if (((unsigned int)eth_data & (GRETH_BUF_ALIGN - 1)) && !greth->gbit_mac) { /* data not aligned as needed by GRETH 10/100, solve this by allocating 4 byte aligned buffer * and copy data to before giving it to GRETH. */ if (!greth->txbuf) { greth->txbuf = malloc(GRETH_RXBUF_SIZE);#ifdef DEBUG printf("GRETH: allocated aligned tx-buf\n");#endif } txbuf = greth->txbuf; /* copy data info buffer */ memcpy((char *)txbuf, (char *)eth_data, data_length); /* keep buffer to next time */ } else { txbuf = (void *)eth_data; } /* get descriptor to use, only 1 supported... hehe easy */ txbd = greth->txbd_base; /* setup descriptor to wrap around to it self */ txbd->addr = (unsigned int)txbuf; txbd->stat = GRETH_BD_EN | GRETH_BD_WR | data_length; /* Remind Core which descriptor to use when sending */ GRETH_REGSAVE(®s->tx_desc_p, (unsigned int)txbd); /* initate send by enabling transmitter */ GRETH_REGORIN(®s->control, GRETH_TXEN); /* Wait for data to be sent */ while ((status = GRETH_REGLOAD(&txbd->stat)) & GRETH_BD_EN) { ; } /* was the packet transmitted succesfully? */ if (status & GRETH_TXBD_ERR_AL) { greth->stats.tx_limit_errors++; } if (status & GRETH_TXBD_ERR_UE) { greth->stats.tx_underrun_errors++; } if (status & GRETH_TXBD_ERR_LC) { greth->stats.tx_latecol_errors++; } if (status & (GRETH_TXBD_ERR_LC | GRETH_TXBD_ERR_UE | GRETH_TXBD_ERR_AL)) { /* any error */ greth->stats.tx_errors++; return -1; } /* bump tx packet counter */ greth->stats.tx_packets++; /* return succefully */ return 0;}int greth_recv(struct eth_device *dev){ greth_priv *greth = dev->priv; greth_regs *regs = greth->regs; greth_bd *rxbd; unsigned int status, len = 0, bad; unsigned char *d; int enable = 0; int i;#ifdef DEBUG/* printf("greth_recv\n"); */#endif /* Receive One packet only, but clear as many error packets as there are * available. */ { /* current receive descriptor */ rxbd = greth->rxbd_curr; /* get status of next received packet */ status = GRETH_REGLOAD(&rxbd->stat); bad = 0; /* stop if no more packets received */ if (status & GRETH_BD_EN) { goto done; }#ifdef DEBUG printf("greth_recv: packet 0x%lx, 0x%lx, len: %d\n", (unsigned int)rxbd, status, status & GRETH_BD_LEN);#endif /* Check status for errors. */ if (status & GRETH_RXBD_ERR_FT) { greth->stats.rx_length_errors++; bad = 1; } if (status & (GRETH_RXBD_ERR_AE | GRETH_RXBD_ERR_OE)) { greth->stats.rx_frame_errors++; bad = 1; } if (status & GRETH_RXBD_ERR_CRC) { greth->stats.rx_crc_errors++; bad = 1; } if (bad) { greth->stats.rx_errors++; printf ("greth_recv: Bad packet (%d, %d, %d, 0x%08x, %d)\n", greth->stats.rx_length_errors, greth->stats.rx_frame_errors, greth->stats.rx_crc_errors, status, greth->stats.rx_packets); /* print all rx descriptors */ for (i = 0; i < GRETH_RXBD_CNT; i++) { printf("[%d]: Stat=0x%lx, Addr=0x%lx\n", i, GRETH_REGLOAD(&greth->rxbd_base[i].stat), GRETH_REGLOAD(&greth->rxbd_base[i]. addr)); } } else { /* Process the incoming packet. */ len = status & GRETH_BD_LEN; d = (char *)rxbd->addr;#ifdef DEBUG printf ("greth_recv: new packet, length: %d. data: %x %x %x %x %x %x %x %x\n", len, d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7]);#endif /* flush all data cache to make sure we're not reading old packet data */ sparc_dcache_flush_all(); /* pass packet on to network subsystem */ NetReceive((void *)d, len); /* bump stats counters */ greth->stats.rx_packets++; /* bad is now 0 ==> will stop loop */ } /* reenable descriptor to receive more packet with this descriptor, wrap around if needed */ rxbd->stat = GRETH_BD_EN | (((unsigned int)greth->rxbd_curr >= (unsigned int)greth->rxbd_max) ? GRETH_BD_WR : 0); enable = 1; /* increase index */ greth->rxbd_curr = ((unsigned int)greth->rxbd_curr >= (unsigned int)greth->rxbd_max) ? greth-> rxbd_base : (greth->rxbd_curr + 1); }; if (enable) { GRETH_REGORIN(®s->control, GRETH_RXEN); } done: /* return positive length of packet or 0 if non recieved */ return len;}void greth_set_hwaddr(greth_priv * greth, unsigned char *mac){ /* save new MAC address */ greth->dev->enetaddr[0] = greth->hwaddr[0] = mac[0]; greth->dev->enetaddr[1] = greth->hwaddr[1] = mac[1]; greth->dev->enetaddr[2] = greth->hwaddr[2] = mac[2]; greth->dev->enetaddr[3] = greth->hwaddr[3] = mac[3]; greth->dev->enetaddr[4] = greth->hwaddr[4] = mac[4]; greth->dev->enetaddr[5] = greth->hwaddr[5] = mac[5]; greth->regs->esa_msb = (mac[0] << 8) | mac[1]; greth->regs->esa_lsb = (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5];#ifdef DEBUG printf("GRETH: New MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);#endif}int greth_initialize(bd_t * bis){ greth_priv *greth; ambapp_apbdev apbdev; struct eth_device *dev; int i; char *addr_str, *end; unsigned char addr[6];#ifdef DEBUG printf("Scanning for GRETH\n");#endif /* Find Device & IRQ via AMBA Plug&Play information */ if (ambapp_apb_first(VENDOR_GAISLER, GAISLER_ETHMAC, &apbdev) != 1) { return -1; /* GRETH not found */ } greth = (greth_priv *) malloc(sizeof(greth_priv)); dev = (struct eth_device *)malloc(sizeof(struct eth_device)); memset(dev, 0, sizeof(struct eth_device)); memset(greth, 0, sizeof(greth_priv)); greth->regs = (greth_regs *) apbdev.address; greth->irq = apbdev.irq;#ifdef DEBUG printf("Found GRETH at 0x%lx, irq %d\n", greth->regs, greth->irq);#endif dev->priv = (void *)greth; dev->iobase = (unsigned int)greth->regs; dev->init = greth_init; dev->halt = greth_halt; dev->send = greth_send; dev->recv = greth_recv; greth->dev = dev; /* Reset Core */ GRETH_REGSAVE(&greth->regs->control, GRETH_RESET); /* Wait for core to finish reset cycle */ while (GRETH_REGLOAD(&greth->regs->control) & GRETH_RESET) ; /* Get the phy address which assumed to have been set correctly with the reset value in hardware */ greth->phyaddr = (GRETH_REGLOAD(&greth->regs->mdio) >> 11) & 0x1F; /* Check if mac is gigabit capable */ greth->gbit_mac = (GRETH_REGLOAD(&greth->regs->control) >> 27) & 1; /* Make descriptor string */ if (greth->gbit_mac) { sprintf(dev->name, "GRETH 10/100/GB"); } else { sprintf(dev->name, "GRETH 10/100"); } /* initiate PHY, select speed/duplex depending on connected PHY */ if (greth_init_phy(greth, bis)) { /* Failed to init PHY (timedout) */ return -1; } /* Register Device to EtherNet subsystem */ eth_register(dev); /* Get MAC address */ if ((addr_str = getenv("ethaddr")) != NULL) { for (i = 0; i < 6; i++) { addr[i] = addr_str ? simple_strtoul(addr_str, &end, 16) : 0; if (addr_str) { addr_str = (*end) ? end + 1 : end; } } } else { /* HW Address not found in environment, Set default HW address */ addr[0] = GRETH_HWADDR_0; /* MSB */ addr[1] = GRETH_HWADDR_1; addr[2] = GRETH_HWADDR_2; addr[3] = GRETH_HWADDR_3; addr[4] = GRETH_HWADDR_4; addr[5] = GRETH_HWADDR_5; /* LSB */ } /* set and remember MAC address */ greth_set_hwaddr(greth, addr); return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -