static int rtl_transmit(struct eth_device *dev, volatile void *packet, int length) { unsigned int status; unsigned long txstatus; unsigned int len = length; int i = 0; ioaddr = dev->iobase; memcpy((char *)tx_buffer, (char *)packet, (int)length); #ifdef DEBUG_TX printf("sending %d bytes\n", len); #endif /* Note: RTL8139 doesn't auto-pad, send minimum payload (another 4 * bytes are sent automatically for the FCS, totalling to 64 bytes). */ while (len < ETH_ZLEN) { tx_buffer[len++] = '\0'; } flush_cache((unsigned long)tx_buffer, length); outl(phys_to_bus((int)tx_buffer), ioaddr + TxAddr0 + cur_tx*4); outl(((TX_FIFO_THRESH<<11) & 0x003f0000) | len, ioaddr + TxStatus0 + cur_tx*4); do { status = inw(ioaddr + IntrStatus); /* Only acknlowledge interrupt sources we can properly handle * here - the RxOverflow/RxFIFOOver MUST be handled in the * rtl_poll() function. */ outw(status & (TxOK | TxErr | PCIErr), ioaddr + IntrStatus); if ((status & (TxOK | TxErr | PCIErr)) != 0) break; udelay(10); } while (i++ < RTL_TIMEOUT); txstatus = inl(ioaddr + TxStatus0 + cur_tx*4); if (status & TxOK) { cur_tx = (cur_tx + 1) % NUM_TX_DESC; #ifdef DEBUG_TX printf("tx done (%d ticks), status %hX txstatus %X\n", to-currticks(), status, txstatus); #endif return length; } else { #ifdef DEBUG_TX printf("tx timeout/error (%d usecs), status %hX txstatus %X\n", 10*i, status, txstatus); #endif rtl_reset(dev); return 0; } }
/** * "time" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int time_exec ( int argc, char **argv ) { struct time_options opts; unsigned long start; unsigned long elapsed; int decisecs; int rc; /* Parse options */ if ( ( rc = parse_options ( argc, argv, &time_cmd, &opts ) ) != 0 ) return rc; start = currticks(); rc = execv ( argv[1], argv + 1 ); elapsed = ( currticks() - start ); decisecs = ( 10 * elapsed / ticks_per_sec() ); printf ( "%s: %d.%ds\n", argv[0], ( decisecs / 10 ), ( decisecs % 10 ) ); return rc; }
int ReadMII (int byMIIIndex, int ioaddr) { int ReturnMII; char byMIIAdrbak; char byMIICRbak; char byMIItemp; unsigned long ct; byMIIAdrbak = inb (byMIIAD); byMIICRbak = inb (byMIICR); outb (byMIICRbak & 0x7f, byMIICR); MIIDelay (); outb (byMIIIndex, byMIIAD); MIIDelay (); outb (inb (byMIICR) | 0x40, byMIICR); byMIItemp = inb (byMIICR); byMIItemp = byMIItemp & 0x40; ct = currticks(); while (byMIItemp != 0 && ct + 2*1000 < currticks()) { byMIItemp = inb (byMIICR); byMIItemp = byMIItemp & 0x40; } MIIDelay (); ReturnMII = inw (wMIIDATA); outb (byMIIAdrbak, byMIIAD); outb (byMIICRbak, byMIICR); MIIDelay (); return (ReturnMII); }
/* send a test packet - return true if carrier bits are ok */ static int send_test_pkt(struct nic *nic) { static unsigned char testpacket[] = { 0,0,0,0,0,0, 0,0,0,0,0,0, 0, 46, /*A 46 in network order */ 0, 0, /*DSAP=0 & SSAP=0 fields */ 0xf3,0 /*Control (Test Req+P bit set)*/ }; unsigned long tmo; writereg(PP_LineCTL, readreg(PP_LineCTL) | SERIAL_TX_ON); memcpy(testpacket, nic->node_addr, ETH_ALEN); memcpy(testpacket+ETH_ALEN, nic->node_addr, ETH_ALEN); outw(TX_AFTER_ALL, eth_nic_base + TX_CMD_PORT); outw(ETH_ZLEN, eth_nic_base + TX_LEN_PORT); /* Test to see if the chip has allocated memory for the packet */ for (tmo = currticks() + 2; (readreg(PP_BusST) & READY_FOR_TX_NOW) == 0; ) if (currticks() >= tmo) return(0); /* Write the contents of the packet */ outsw(eth_nic_base + TX_FRAME_PORT, testpacket, (ETH_ZLEN+1)>>1); printf(" sending test packet "); /* wait a couple of timer ticks for packet to be received */ for (tmo = currticks() + 2; currticks() < tmo; ); if ((readreg(PP_TxEvent) & TX_SEND_OK_BITS) == TX_OK) { printf("succeeded"); return 1; } printf("failed"); return 0; }
/************************************************************************** RESET - Finish setting up the ethernet interface ***************************************************************************/ static int rtl_reset(struct eth_device *dev, bd_t *bis) { int i; #ifdef DEBUG_RTL8169 int stime = currticks(); printf ("%s\n", __FUNCTION__); #endif tpc->TxDescArrays = tx_ring; /* Tx Desscriptor needs 256 bytes alignment; */ tpc->TxDescArray = (struct TxDesc *) ((unsigned long)(tpc->TxDescArrays + 255) & ~255); tpc->RxDescArrays = rx_ring; /* Rx Desscriptor needs 256 bytes alignment; */ tpc->RxDescArray = (struct RxDesc *) ((unsigned long)(tpc->RxDescArrays + 255) & ~255); rtl8169_init_ring(dev); rtl8169_hw_start(dev); /* Construct a perfect filter frame with the mac address as first match * and broadcast for all others */ for (i = 0; i < 192; i++) txb[i] = 0xFF; txb[0] = dev->enetaddr[0]; txb[1] = dev->enetaddr[1]; txb[2] = dev->enetaddr[2]; txb[3] = dev->enetaddr[3]; txb[4] = dev->enetaddr[4]; txb[5] = dev->enetaddr[5]; #ifdef DEBUG_RTL8169 printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime); #endif return 0; }
/** * Generate a pseudo-random number between 0 and 2147483647L or 2147483562? * * @ret rand Pseudo-random number */ long int random ( void ) { int32_t q; if ( ! rnd_seed ) /* Initialize linear congruential generator */ srandom ( currticks() ); /* simplified version of the LCG given in Bruce Schneier's "Applied Cryptography" */ q = ( rnd_seed / 53668 ); rnd_seed = ( 40014 * ( rnd_seed - 53668 * q ) - 12211 * q ); if ( rnd_seed < 0 ) rnd_seed += 2147483563L; return rnd_seed; }
static void rtl8169_init_ring(struct eth_device *dev) { int i; #ifdef DEBUG_RTL8169 int stime = currticks(); printf ("%s\n", __FUNCTION__); #endif tpc->cur_rx = 0; tpc->cur_tx = 0; tpc->dirty_tx = 0; memset(tpc->TxDescArray, 0x0, NUM_TX_DESC * sizeof(struct TxDesc)); memset(tpc->RxDescArray, 0x0, NUM_RX_DESC * sizeof(struct RxDesc)); for (i = 0; i < NUM_TX_DESC; i++) { tpc->Tx_skbuff[i] = &txb[i]; } for (i = 0; i < NUM_RX_DESC; i++) { if (i == (NUM_RX_DESC - 1)) tpc->RxDescArray[i].status = cpu_to_le32((OWNbit | EORbit) + RX_BUF_SIZE); else tpc->RxDescArray[i].status = cpu_to_le32(OWNbit + RX_BUF_SIZE); tpc->RxBufferRing[i] = &rxb[i * RX_BUF_SIZE]; tpc->RxDescArray[i].buf_addr = cpu_to_le32(bus_to_phys(tpc->RxBufferRing[i])); rtl_flush_rx_desc(&tpc->RxDescArray[i]); } #ifdef DEBUG_RTL8169 printf("%s elapsed time : %lu\n", __func__, currticks()-stime); #endif }
void twiddle (void) { static unsigned long lastticks = 0; static int count = 0; static const char tiddles[]="-\\|/"; unsigned long ticks; if (debug) { if ((ticks = currticks ()) == lastticks) return; lastticks = ticks; grub_putchar (tiddles[(count++) & 3]); grub_putchar ('\b'); } }
/** * Stop timer * * @v timer Retry timer * * This stops the timer and updates the timer's timeout value. */ void stop_timer ( struct retry_timer *timer ) { unsigned long old_timeout = timer->timeout; unsigned long now = currticks(); unsigned long runtime; /* If timer was already stopped, do nothing */ if ( ! timer->running ) return; list_del ( &timer->list ); runtime = ( now - timer->start ); timer->running = 0; DBG2 ( "Timer %p stopped at time %ld (ran for %ld)\n", timer, now, runtime ); /* Update timer. Variables are: * * r = round-trip time estimate (i.e. runtime) * t = timeout value (i.e. timer->timeout) * s = smoothed round-trip time * * By choice, we set t = 4s, i.e. allow for four times the * normal round-trip time to pass before retransmitting. * * We want to smooth according to s := ( 7 s + r ) / 8 * * Since we don't actually store s, this reduces to * t := ( 7 t / 8 ) + ( r / 2 ) * */ if ( timer->count ) { timer->count--; } else { timer->timeout -= ( timer->timeout >> 3 ); timer->timeout += ( runtime >> 1 ); if ( timer->timeout != old_timeout ) { DBG ( "Timer %p timeout updated to %ld\n", timer, timer->timeout ); } } ref_put ( timer->refcnt ); }
/** * Start timer * * @v timer Retry timer * * This starts the timer running with the current timeout value. If * stop_timer() is not called before the timer expires, the timer will * be stopped and the timer's callback function will be called. */ void start_timer ( struct retry_timer *timer ) { if ( ! timer->running ) { list_add ( &timer->list, &timers ); ref_get ( timer->refcnt ); } timer->start = currticks(); timer->running = 1; /* 0 means "use default timeout" */ if ( timer->min_timeout == 0 ) timer->min_timeout = DEFAULT_MIN_TIMEOUT; /* We must never be less than MIN_TIMEOUT under any circumstances */ if ( timer->min_timeout < MIN_TIMEOUT ) timer->min_timeout = MIN_TIMEOUT; /* Honor user-specified minimum timeout */ if ( timer->timeout < timer->min_timeout ) timer->timeout = timer->min_timeout; DBG2 ( "Timer %p started at time %ld (expires at %ld)\n", timer, timer->start, ( timer->start + timer->timeout ) ); }
static int rtl_send_common(pci_dev_t dev, unsigned long dev_iobase, void *packet, int length) #endif { /* send the packet to destination */ u32 to; u8 *ptxb; int entry = tpc->cur_tx % NUM_TX_DESC; u32 len = length; int ret; #ifdef DEBUG_RTL8169_TX int stime = currticks(); printf ("%s\n", __FUNCTION__); printf("sending %d bytes\n", len); #endif ioaddr = dev_iobase; /* point to the current txb incase multiple tx_rings are used */ ptxb = tpc->Tx_skbuff[entry * MAX_ETH_FRAME_SIZE]; memcpy(ptxb, (char *)packet, (int)length); while (len < ETH_ZLEN) ptxb[len++] = '\0'; rtl_flush_buffer(ptxb, ALIGN(len, RTL8169_ALIGN)); tpc->TxDescArray[entry].buf_Haddr = 0; #ifdef CONFIG_DM_ETH tpc->TxDescArray[entry].buf_addr = cpu_to_le32( dm_pci_mem_to_phys(dev, (pci_addr_t)(unsigned long)ptxb)); #else tpc->TxDescArray[entry].buf_addr = cpu_to_le32( pci_mem_to_phys(dev, (pci_addr_t)(unsigned long)ptxb)); #endif if (entry != (NUM_TX_DESC - 1)) { tpc->TxDescArray[entry].status = cpu_to_le32((OWNbit | FSbit | LSbit) | ((len > ETH_ZLEN) ? len : ETH_ZLEN)); } else { tpc->TxDescArray[entry].status = cpu_to_le32((OWNbit | EORbit | FSbit | LSbit) | ((len > ETH_ZLEN) ? len : ETH_ZLEN)); } rtl_flush_tx_desc(&tpc->TxDescArray[entry]); RTL_W8(TxPoll, 0x40); /* set polling bit */ tpc->cur_tx++; to = currticks() + TX_TIMEOUT; do { rtl_inval_tx_desc(&tpc->TxDescArray[entry]); } while ((le32_to_cpu(tpc->TxDescArray[entry].status) & OWNbit) && (currticks() < to)); /* wait */ if (currticks() >= to) { #ifdef DEBUG_RTL8169_TX puts("tx timeout/error\n"); printf("%s elapsed time : %lu\n", __func__, currticks()-stime); #endif ret = -ETIMEDOUT; } else { #ifdef DEBUG_RTL8169_TX puts("tx done\n"); #endif ret = 0; } /* Delay to make net console (nc) work properly */ udelay(20); return ret; }
timer, timer->timeout ); /* Call expiry callback */ timer->expired ( timer, fail ); ref_put ( timer->refcnt ); } /** * Single-step the retry timer list * * @v process Retry timer process */ static void retry_step ( struct process *process __unused ) { struct retry_timer *timer; unsigned long now = currticks(); unsigned long used; /* Process at most one timer expiry. We cannot process * multiple expiries in one pass, because one timer expiring * may end up triggering another timer's deletion from the * list. */ list_for_each_entry ( timer, &timers, list ) { used = ( now - timer->start ); if ( used >= timer->timeout ) { timer_expired ( timer ); break; } } }
int bootp (void) { int retry; #ifndef NO_DHCP_SUPPORT int reqretry; #endif /* ! NO_DHCP_SUPPORT */ struct bootpip_t ip; unsigned long starttime; /* Make sure that an ethernet is probed. */ if (! eth_probe ()) return 0; /* Clear the ready flag. */ network_ready = 0; #ifdef DEBUG grub_printf ("network is ready.\n"); #endif grub_memset (&ip, 0, sizeof (struct bootpip_t)); ip.bp.bp_op = BOOTP_REQUEST; ip.bp.bp_htype = 1; ip.bp.bp_hlen = ETH_ALEN; starttime = currticks (); /* Use lower 32 bits of node address, more likely to be distinct than the time since booting */ grub_memmove (&xid, &arptable[ARP_CLIENT].node[2], sizeof(xid)); ip.bp.bp_xid = xid += htonl (starttime); grub_memmove (ip.bp.bp_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN); #ifdef DEBUG etherboot_printf ("bp_op = %d\n", ip.bp.bp_op); etherboot_printf ("bp_htype = %d\n", ip.bp.bp_htype); etherboot_printf ("bp_hlen = %d\n", ip.bp.bp_hlen); etherboot_printf ("bp_xid = %d\n", ip.bp.bp_xid); etherboot_printf ("bp_hwaddr = %!\n", ip.bp.bp_hwaddr); etherboot_printf ("bp_hops = %d\n", (int) ip.bp.bp_hops); etherboot_printf ("bp_secs = %d\n", (int) ip.bp.bp_hwaddr); #endif #ifdef NO_DHCP_SUPPORT /* Request RFC-style options. */ grub_memmove (ip.bp.bp_vend, rfc1533_cookie, 5); #else /* Request RFC-style options. */ grub_memmove (ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie); grub_memmove (ip.bp.bp_vend + sizeof rfc1533_cookie, dhcpdiscover, sizeof dhcpdiscover); grub_memmove (ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcpdiscover, rfc1533_end, sizeof rfc1533_end); #endif /* ! NO_DHCP_SUPPORT */ for (retry = 0; retry < MAX_BOOTP_RETRIES;) { long timeout; #ifdef DEBUG grub_printf ("retry = %d\n", retry); #endif /* Clear out the Rx queue first. It contains nothing of * interest, except possibly ARP requests from the DHCP/TFTP * server. We use polling throughout Etherboot, so some time * may have passed since we last polled the receive queue, * which may now be filled with broadcast packets. This will * cause the reply to the packets we are about to send to be * lost immediately. Not very clever. */ await_reply (AWAIT_QDRAIN, 0, NULL, 0); udp_transmit (IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER, sizeof (struct bootpip_t), &ip); timeout = rfc2131_sleep_interval (TIMEOUT, retry++); #ifdef NO_DHCP_SUPPORT if (await_reply (AWAIT_BOOTP, 0, NULL, timeout)) { network_ready = 1; return 1; } #else /* ! NO_DHCP_SUPPORT */ if (await_reply (AWAIT_BOOTP, 0, NULL, timeout)) { if (dhcp_reply != DHCPOFFER) { network_ready = 1; return 1; } dhcp_reply = 0; #ifdef DEBUG etherboot_printf ("bp_op = %d\n", (int) ip.bp.bp_op); etherboot_printf ("bp_htype = %d\n", (int) ip.bp.bp_htype); etherboot_printf ("bp_hlen = %d\n", (int) ip.bp.bp_hlen); etherboot_printf ("bp_xid = %d\n", (int) ip.bp.bp_xid); etherboot_printf ("bp_hwaddr = %!\n", ip.bp.bp_hwaddr); etherboot_printf ("bp_hops = %d\n", (int) ip.bp.bp_hops); etherboot_printf ("bp_secs = %d\n", (int) ip.bp.bp_hwaddr); #endif grub_memmove (ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie); grub_memmove (ip.bp.bp_vend + sizeof rfc1533_cookie, dhcprequest, sizeof dhcprequest); grub_memmove (ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcprequest, rfc1533_end, sizeof rfc1533_end); grub_memmove (ip.bp.bp_vend + 9, (char *) &dhcp_server, sizeof (in_addr)); grub_memmove (ip.bp.bp_vend + 15, (char *) &dhcp_addr, sizeof (in_addr)); #ifdef DEBUG grub_printf ("errnum = %d\n", errnum); #endif for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES;) { int ret; #ifdef DEBUG grub_printf ("reqretry = %d\n", reqretry); #endif ret = udp_transmit (IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER, sizeof (struct bootpip_t), &ip); if (! ret) grub_printf ("udp_transmit failed.\n"); dhcp_reply = 0; timeout = rfc2131_sleep_interval (TIMEOUT, reqretry++); if (await_reply (AWAIT_BOOTP, 0, NULL, timeout)) if (dhcp_reply == DHCPACK) { network_ready = 1; return 1; } #ifdef DEBUG grub_printf ("dhcp_reply = %d\n", dhcp_reply); #endif if (ip_abort) return 0; } } #endif /* ! NO_DHCP_SUPPORT */ if (ip_abort) return 0; ip.bp.bp_secs = htons ((currticks () - starttime) / TICKS_PER_SEC); } /* Timeout. */ return 0; }
void WriteMII (char byMIISetByte, char byMIISetBit, char byMIIOP, int ioaddr) { int ReadMIItmp; int MIIMask; char byMIIAdrbak; char byMIICRbak; char byMIItemp; unsigned long ct; byMIIAdrbak = inb (byMIIAD); byMIICRbak = inb (byMIICR); outb (byMIICRbak & 0x7f, byMIICR); MIIDelay (); outb (byMIISetByte, byMIIAD); MIIDelay (); outb (inb (byMIICR) | 0x40, byMIICR); byMIItemp = inb (byMIICR); byMIItemp = byMIItemp & 0x40; ct = currticks(); while (byMIItemp != 0 && ct + 2*1000 < currticks()) { byMIItemp = inb (byMIICR); byMIItemp = byMIItemp & 0x40; } MIIDelay (); ReadMIItmp = inw (wMIIDATA); MIIMask = 0x0001; MIIMask = MIIMask << byMIISetBit; if (byMIIOP == 0) { MIIMask = ~MIIMask; ReadMIItmp = ReadMIItmp & MIIMask; } else { ReadMIItmp = ReadMIItmp | MIIMask; } outw (ReadMIItmp, wMIIDATA); MIIDelay (); outb (inb (byMIICR) | 0x20, byMIICR); byMIItemp = inb (byMIICR); byMIItemp = byMIItemp & 0x20; ct = currticks(); while (byMIItemp != 0 && ct + 2*1000 < currticks()) { byMIItemp = inb (byMIICR); byMIItemp = byMIItemp & 0x20; } MIIDelay (); outb (byMIIAdrbak & 0x7f, byMIIAD); outb (byMIICRbak, byMIICR); MIIDelay (); }
static void w89c840_transmit( struct nic *nic, const char *d, /* Destination */ unsigned int t, /* Type */ unsigned int s, /* size */ const char *p) /* Packet */ { /* send the packet to destination */ unsigned entry; int transmit_status; unsigned long ct; /* Caution: the write order is important here, set the field with the "ownership" bits last. */ /* Fill in our transmit buffer */ entry = w840private.cur_tx % TX_RING_SIZE; memcpy (w89c840_buf.tx_packet, d, ETH_ALEN); /* dst */ memcpy (w89c840_buf.tx_packet + ETH_ALEN, nic->node_addr, ETH_ALEN);/*src*/ *((char *) w89c840_buf.tx_packet + 12) = t >> 8; /* type */ *((char *) w89c840_buf.tx_packet + 13) = t; memcpy (w89c840_buf.tx_packet + ETH_HLEN, p, s); s += ETH_HLEN; while (s < ETH_ZLEN) *((char *) w89c840_buf.tx_packet + ETH_HLEN + (s++)) = 0; w840private.tx_ring[entry].buffer1 = virt_to_le32desc(w89c840_buf.tx_packet); w840private.tx_ring[entry].length = (DescWholePkt | (u32) s); if (entry >= TX_RING_SIZE-1) /* Wrap ring */ w840private.tx_ring[entry].length |= (DescIntr | DescEndRing); w840private.tx_ring[entry].status = (DescOwn); w840private.cur_tx++; w840private.tx_q_bytes = (u16) s; writel(0, ioaddr + TxStartDemand); /* Work around horrible bug in the chip by marking the queue as full when we do not have FIFO room for a maximum sized packet. */ if ((w840private.drv_flags & HasBrokenTx) && w840private.tx_q_bytes > TX_BUG_FIFO_LIMIT) { /* Actually this is left to help finding error tails later in debugging... * See Linux kernel driver in winbond-840.c for details. */ w840private.tx_full = 1; } #if defined(W89C840_DEBUG) printf("winbond-840 : Transmit frame # %d size %d queued in slot %d.\n", w840private.cur_tx, s, entry); #endif /* Now wait for TX to complete. */ transmit_status = w840private.tx_ring[entry].status; ct = currticks(); { #if defined W89C840_DEBUG u32 intr_stat = 0; #endif while (1) { #if defined(W89C840_DEBUG) decode_interrupt(intr_stat); #endif while ( (transmit_status & DescOwn) && ct + TX_TIMEOUT < currticks()) { transmit_status = w840private.tx_ring[entry].status; } break; } } if ((transmit_status & DescOwn) == 0) { #if defined(W89C840_DEBUG) printf("winbond-840 : transmission complete after wait loop iterations, status %X\n", w840private.tx_ring[entry].status); #endif return; } /* Transmit timed out... */ printf("winbond-840 : transmission TIMEOUT : status %X\n", (unsigned int) w840private.tx_ring[entry].status); return; }
static void rtl8169_hw_start(pci_dev_t dev) #endif { u32 i; #ifdef DEBUG_RTL8169 int stime = currticks(); printf ("%s\n", __FUNCTION__); #endif #if 0 /* Soft reset the chip. */ RTL_W8(ChipCmd, CmdReset); /* Check that the chip has finished the reset. */ for (i = 1000; i > 0; i--) { if ((RTL_R8(ChipCmd) & CmdReset) == 0) break; else udelay(10); } #endif RTL_W8(Cfg9346, Cfg9346_Unlock); /* RTL-8169sb/8110sb or previous version */ if (tpc->chipset <= 5) RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); RTL_W8(EarlyTxThres, EarlyTxThld); /* For gigabit rtl8169 */ RTL_W16(RxMaxSize, RxPacketMaxSize); /* Set Rx Config register */ i = rtl8169_rx_config | (RTL_R32(RxConfig) & rtl_chip_info[tpc->chipset].RxConfigMask); RTL_W32(RxConfig, i); /* Set DMA burst size and Interframe Gap Time */ RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | (InterFrameGap << TxInterFrameGapShift)); tpc->cur_rx = 0; #ifdef CONFIG_DM_ETH RTL_W32(TxDescStartAddrLow, dm_pci_mem_to_phys(dev, (pci_addr_t)(unsigned long)tpc->TxDescArray)); #else RTL_W32(TxDescStartAddrLow, pci_mem_to_phys(dev, (pci_addr_t)(unsigned long)tpc->TxDescArray)); #endif RTL_W32(TxDescStartAddrHigh, (unsigned long)0); #ifdef CONFIG_DM_ETH RTL_W32(RxDescStartAddrLow, dm_pci_mem_to_phys( dev, (pci_addr_t)(unsigned long)tpc->RxDescArray)); #else RTL_W32(RxDescStartAddrLow, pci_mem_to_phys( dev, (pci_addr_t)(unsigned long)tpc->RxDescArray)); #endif RTL_W32(RxDescStartAddrHigh, (unsigned long)0); /* RTL-8169sc/8110sc or later version */ if (tpc->chipset > 5) RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); RTL_W8(Cfg9346, Cfg9346_Lock); udelay(10); RTL_W32(RxMissed, 0); rtl8169_set_rx_mode(); /* no early-rx interrupts */ RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); #ifdef DEBUG_RTL8169 printf("%s elapsed time : %lu\n", __func__, currticks()-stime); #endif }
/************************************************************************** SEND - Transmit a frame ***************************************************************************/ static int rtl_send(struct eth_device *dev, volatile void *packet, int length) { /* send the packet to destination */ u32 to; u8 *ptxb; int entry = tpc->cur_tx % NUM_TX_DESC; u32 len = length; int ret; #ifdef DEBUG_RTL8169_TX int stime = currticks(); printf ("%s\n", __FUNCTION__); printf("sending %d bytes\n", len); #endif ioaddr = dev->iobase; /* point to the current txb incase multiple tx_rings are used */ ptxb = tpc->Tx_skbuff[entry * MAX_ETH_FRAME_SIZE]; memcpy(ptxb, (char *)packet, (int)length); flush_cache((unsigned long)ptxb, length); while (len < ETH_ZLEN) ptxb[len++] = '\0'; tpc->TxDescArray[entry].buf_Haddr = 0; tpc->TxDescArray[entry].buf_addr = cpu_to_le32(bus_to_phys(ptxb)); if (entry != (NUM_TX_DESC - 1)) { tpc->TxDescArray[entry].status = cpu_to_le32((OWNbit | FSbit | LSbit) | ((len > ETH_ZLEN) ? len : ETH_ZLEN)); } else { tpc->TxDescArray[entry].status = cpu_to_le32((OWNbit | EORbit | FSbit | LSbit) | ((len > ETH_ZLEN) ? len : ETH_ZLEN)); } RTL_W8(TxPoll, 0x40); /* set polling bit */ tpc->cur_tx++; to = currticks() + TX_TIMEOUT; do { flush_cache((unsigned long)&tpc->TxDescArray[entry], sizeof(struct TxDesc)); } while ((le32_to_cpu(tpc->TxDescArray[entry].status) & OWNbit) && (currticks() < to)); /* wait */ if (currticks() >= to) { #ifdef DEBUG_RTL8169_TX puts ("tx timeout/error\n"); printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime); #endif ret = 0; } else { #ifdef DEBUG_RTL8169_TX puts("tx done\n"); #endif ret = length; } /* Delay to make net console (nc) work properly */ udelay(20); return ret; }
static void davicom_wait(unsigned int nticks) { unsigned int to = currticks() + nticks; while (currticks() < to) /* wait */ ; }
int bootp (void) { int retry; #ifndef NO_DHCP_SUPPORT int reqretry; #endif struct bootpip_t ip; unsigned long starttime; if (! eth_probe ()) return 0; network_ready = 0; #ifdef DEBUG grub_printf ("network is ready.\n"); #endif grub_memset (&ip, 0, sizeof (struct bootpip_t)); ip.bp.bp_op = BOOTP_REQUEST; ip.bp.bp_htype = 1; ip.bp.bp_hlen = ETH_ALEN; starttime = currticks (); grub_memmove (&xid, &arptable[ARP_CLIENT].node[2], sizeof(xid)); ip.bp.bp_xid = xid += htonl (starttime); grub_memmove (ip.bp.bp_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN); #ifdef DEBUG etherboot_printf ("bp_op = %d\n", ip.bp.bp_op); etherboot_printf ("bp_htype = %d\n", ip.bp.bp_htype); etherboot_printf ("bp_hlen = %d\n", ip.bp.bp_hlen); etherboot_printf ("bp_xid = %d\n", ip.bp.bp_xid); etherboot_printf ("bp_hwaddr = %!\n", ip.bp.bp_hwaddr); etherboot_printf ("bp_hops = %d\n", (int) ip.bp.bp_hops); etherboot_printf ("bp_secs = %d\n", (int) ip.bp.bp_hwaddr); #endif #ifdef NO_DHCP_SUPPORT grub_memmove (ip.bp.bp_vend, rfc1533_cookie, 5); #else grub_memmove (ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie); grub_memmove (ip.bp.bp_vend + sizeof rfc1533_cookie, dhcpdiscover, sizeof dhcpdiscover); grub_memmove (ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcpdiscover, rfc1533_end, sizeof rfc1533_end); #endif for (retry = 0; retry < MAX_BOOTP_RETRIES;) { long timeout; #ifdef DEBUG grub_printf ("retry = %d\n", retry); #endif await_reply (AWAIT_QDRAIN, 0, NULL, 0); udp_transmit (IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER, sizeof (struct bootpip_t), &ip); timeout = rfc2131_sleep_interval (TIMEOUT, retry++); #ifdef NO_DHCP_SUPPORT if (await_reply (AWAIT_BOOTP, 0, NULL, timeout)) { network_ready = 1; return 1; } #else if (await_reply (AWAIT_BOOTP, 0, NULL, timeout)) { if (dhcp_reply != DHCPOFFER) { network_ready = 1; return 1; } dhcp_reply = 0; #ifdef DEBUG etherboot_printf ("bp_op = %d\n", (int) ip.bp.bp_op); etherboot_printf ("bp_htype = %d\n", (int) ip.bp.bp_htype); etherboot_printf ("bp_hlen = %d\n", (int) ip.bp.bp_hlen); etherboot_printf ("bp_xid = %d\n", (int) ip.bp.bp_xid); etherboot_printf ("bp_hwaddr = %!\n", ip.bp.bp_hwaddr); etherboot_printf ("bp_hops = %d\n", (int) ip.bp.bp_hops); etherboot_printf ("bp_secs = %d\n", (int) ip.bp.bp_hwaddr); #endif grub_memmove (ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie); grub_memmove (ip.bp.bp_vend + sizeof rfc1533_cookie, dhcprequest, sizeof dhcprequest); grub_memmove (ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcprequest, rfc1533_end, sizeof rfc1533_end); grub_memmove (ip.bp.bp_vend + 9, (char *) &dhcp_server, sizeof (in_addr)); grub_memmove (ip.bp.bp_vend + 15, (char *) &dhcp_addr, sizeof (in_addr)); #ifdef DEBUG grub_printf ("errnum = %d\n", errnum); #endif for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES;) { int ret; #ifdef DEBUG grub_printf ("reqretry = %d\n", reqretry); #endif ret = udp_transmit (IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER, sizeof (struct bootpip_t), &ip); if (! ret) grub_printf ("udp_transmit failed.\n"); dhcp_reply = 0; timeout = rfc2131_sleep_interval (TIMEOUT, reqretry++); if (await_reply (AWAIT_BOOTP, 0, NULL, timeout)) if (dhcp_reply == DHCPACK) { network_ready = 1; return 1; } #ifdef DEBUG grub_printf ("dhcp_reply = %d\n", dhcp_reply); #endif if (ip_abort) return 0; } } #endif if (ip_abort) return 0; ip.bp.bp_secs = htons ((currticks () - starttime) / TICKS_PER_SEC); } return 0; }
/************************************************************************** LOAD - Try to get booted **************************************************************************/ load() { char *p,*q; char cfg[64]; int root_mount_port; int swap_nfs_port; int swap_mount_port; char cmd_line[80]; int err, read_size, i; long addr, broadcast; int swsize; unsigned long pad; config_buffer[0]='\0'; /* clear; bootp might fill this up */ /* Initialize this early on */ nfsdiskless.root_args.rsize = 8192; nfsdiskless.root_args.wsize = 8192; nfsdiskless.swap_args.rsize = 8192; nfsdiskless.swap_args.wsize = 8192; nfsdiskless.root_args.sotype = SOCK_DGRAM; nfsdiskless.root_args.flags = (NFSMNT_WSIZE | NFSMNT_RSIZE | NFSMNT_RESVPORT); nfsdiskless.swap_args.sotype = SOCK_DGRAM; nfsdiskless.swap_args.flags = (NFSMNT_WSIZE | NFSMNT_RSIZE | NFSMNT_RESVPORT); /* Find a server to get BOOTP reply from */ if (!arptable[ARP_CLIENT].ipaddr || !arptable[ARP_SERVER].ipaddr) { printf("\nSearching for server...\n"); if (!bootp()) { printf("No Server found.\n"); longjmp(jmp_bootmenu,1); } } printf("My IP %I, Server IP %I, GW IP %I\n", arptable[ARP_CLIENT].ipaddr, arptable[ARP_SERVER].ipaddr, arptable[ARP_GATEWAY].ipaddr); #ifdef MDEBUG printf("\n=>>"); getchar(); #endif /*** check if have got info from bootp ***/ if (config_buffer[0]) goto cfg_done; #ifndef NO_TFTP /* Now use TFTP to load configuration file */ sprintf(cfg,"/tftpboot/freebsd.%I",arptable[ARP_CLIENT].ipaddr); if (tftp(cfg) || tftp(cfg+10)) goto cfg_done; cfg[17]='\0'; if (tftp(cfg) || tftp(cfg+10)) goto cfg_done; sprintf(cfg,"/tftpboot/cfg.%I",arptable[ARP_CLIENT].ipaddr); if (tftp(cfg) || tftp(cfg+10)) goto cfg_done; #endif /* not found; using default values... */ sprintf(config_buffer,"rootfs %I:/usr/diskless_root", arptable[ARP_SERVER].ipaddr); printf("Unable to load config file, guessing:\n\t%s\n", config_buffer); cfg_done: #ifdef MDEBUG printf("\n=>>"); getchar(); #endif p = config_buffer; while(*p) { q = cmd_line; while ((*p != '\n') && (*p)) *(q++) = *(p++); *q = 0; printf("%s\n",cmd_line); execute(cmd_line); if (*p) p++; } #ifdef MDEBUG printf("\n=>>"); getchar(); #endif /* Check to make sure we've got a rootfs */ if (!arptable[ARP_ROOTSERVER].ipaddr) { printf("No ROOT filesystem server!\n"); longjmp(jmp_bootmenu,1); } /* Fill in nfsdiskless.myif */ sprintf(&nfsdiskless.myif.ifra_name,eth_driver); nfsdiskless.myif.ifra_addr.sa_len = sizeof(struct sockaddr); nfsdiskless.myif.ifra_addr.sa_family = AF_INET; addr = htonl(arptable[ARP_CLIENT].ipaddr); bcopy(&addr, &nfsdiskless.myif.ifra_addr.sa_data[2], 4); broadcast = (addr & netmask) | ~netmask; nfsdiskless.myif.ifra_broadaddr.sa_len = sizeof(struct sockaddr); nfsdiskless.myif.ifra_broadaddr.sa_family = AF_INET; bcopy(&broadcast, &nfsdiskless.myif.ifra_broadaddr.sa_data[2], 4); addr = htonl(arptable[ARP_GATEWAY].ipaddr); if (addr) { nfsdiskless.mygateway.sin_len = sizeof(struct sockaddr); nfsdiskless.mygateway.sin_family = AF_INET; bcopy(&addr, &nfsdiskless.mygateway.sin_addr, 4); } else { nfsdiskless.mygateway.sin_len = 0; } nfsdiskless.myif.ifra_mask.sa_len = sizeof(struct sockaddr); nfsdiskless.myif.ifra_mask.sa_family = AF_UNSPEC; bcopy(&netmask, &nfsdiskless.myif.ifra_mask.sa_data[2], 4); rpc_id = currticks(); /* Lookup NFS/MOUNTD ports for SWAP using PORTMAP */ if (arptable[ARP_SWAPSERVER].ipaddr) { char swapfs_fh[32], swapfile[32]; swap_nfs_port = rpclookup(ARP_SWAPSERVER, PROG_NFS, 2); swap_mount_port = rpclookup(ARP_SWAPSERVER, PROG_MOUNT, 1); if ((swap_nfs_port == -1) || (swap_mount_port == -1)) { printf("Unable to get SWAP NFS/MOUNT ports\n"); longjmp(jmp_bootmenu,1); } if (err = nfs_mount(ARP_SWAPSERVER, swap_mount_port, nfsdiskless.swap_hostnam, &swapfs_fh)) { printf("Unable to mount SWAP filesystem: "); nfs_err(err); longjmp(jmp_bootmenu,1); } sprintf(swapfile,"swap.%I",arptable[ARP_CLIENT].ipaddr); if (err = nfs_lookup(ARP_SWAPSERVER, swap_nfs_port, &swapfs_fh, swapfile, &nfsdiskless.swap_fh, &swsize)) { printf("Unable to open %s: ",swapfile); nfs_err(err); longjmp(jmp_bootmenu,1); } if (!nfsdiskless.swap_nblks) { nfsdiskless.swap_nblks = swsize / 1024; printf("Swap size is: %d blocks\n",nfsdiskless.swap_nblks); } nfsdiskless.swap_saddr.sin_len = sizeof(struct sockaddr_in); nfsdiskless.swap_saddr.sin_family = AF_INET; nfsdiskless.swap_saddr.sin_port = htons(swap_nfs_port); nfsdiskless.swap_saddr.sin_addr.s_addr = htonl(arptable[ARP_SWAPSERVER].ipaddr); nfsdiskless.swap_args.timeo = 10; nfsdiskless.swap_args.retrans = 100; } /* Lookup NFS/MOUNTD ports for ROOT using PORTMAP */ root_nfs_port = rpclookup(ARP_ROOTSERVER, PROG_NFS, 2); root_mount_port = rpclookup(ARP_ROOTSERVER, PROG_MOUNT, 1); if ((root_nfs_port == -1) || (root_mount_port == -1)) { printf("Unable to get ROOT NFS/MOUNT ports\n"); longjmp(jmp_bootmenu,1); } if (err = nfs_mount(ARP_ROOTSERVER, root_mount_port, nfsdiskless.root_hostnam, &nfsdiskless.root_fh)) { printf("Unable to mount ROOT filesystem: "); nfs_err(err); longjmp(jmp_bootmenu,1); } nfsdiskless.root_saddr.sin_len = sizeof(struct sockaddr_in); nfsdiskless.root_saddr.sin_family = AF_INET; nfsdiskless.root_saddr.sin_port = htons(root_nfs_port); nfsdiskless.root_saddr.sin_addr.s_addr = htonl(arptable[ARP_ROOTSERVER].ipaddr); nfsdiskless.root_args.timeo = 10; nfsdiskless.root_args.retrans = 100; nfsdiskless.root_time = 0; if (err = nfs_lookup(ARP_ROOTSERVER, root_nfs_port, &nfsdiskless.root_fh, *kernel == '/' ? kernel+1 : kernel, &kernel_handle, NULL)) { printf("Unable to open %s: ",kernel); nfs_err(err); longjmp(jmp_bootmenu,1); } /* Load the kernel using NFS */ printf("Loading %s...\n",kernel); if ((err = nfs_read(ARP_ROOTSERVER, root_nfs_port, &kernel_handle, 0, sizeof(struct exec), &head)) < 0) { printf("Unable to read %s: ",kernel); nfs_err(err); longjmp(jmp_bootmenu,1); } if (N_BADMAG(head)) { printf("Bad executable format!\n"); longjmp(jmp_bootmenu, 1); } loadpoint = (char *)(head.a_entry & 0x00FFFFFF); offset = N_TXTOFF(head); printf("text=0x%X, ",head.a_text); #ifdef PC98 set_twiddle_max(8); #endif nfsload(head.a_text); while (((int)loadpoint) & PAGE_MASK) *(loadpoint++) = 0; printf("data=0x%X, ",head.a_data); nfsload(head.a_data); printf("bss=0x%X, ",head.a_bss); while(head.a_bss--) *(loadpoint++) = 0; while (((int)loadpoint) & PAGE_MASK) *(loadpoint++) = 0; bootinfo.bi_symtab = (int) loadpoint; p = (char*)&head.a_syms; for (i=0;i<sizeof(head.a_syms);i++) *loadpoint++ = *p++; printf("symbols=[+0x%x+0x%x", sizeof(head.a_syms), head.a_syms); nfsload(head.a_syms); i = sizeof(int); p = loadpoint; nfsload(i); i = *(int*)p; printf("+0x%x]\n", i); i -= sizeof(int); nfsload(i); bootinfo.bi_esymtab = (int) loadpoint; printf("entry=0x%X.\n",head.a_entry); /* Jump to kernel */ bootinfo.bi_version = BOOTINFO_VERSION; bootinfo.bi_kernelname = kernel; bootinfo.bi_nfs_diskless = &nfsdiskless; bootinfo.bi_size = sizeof bootinfo; kernelentry = (void *)(head.a_entry & 0x00FFFFFF); (*kernelentry)(howto|RB_BOOTINFO,NODEV,0,0,0,&bootinfo,0,0,0); printf("*** %s execute failure ***\n",kernel); }
static void t3c515_wait(unsigned int nticks) { unsigned int to = currticks() + nticks; while (currticks() < to) /* wait */ ; }
static void sis900_transmit(struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p) { u32 status, to, nstype; u32 tx_status; outl(TxDIS, ioaddr + cr); outl((u32) &txd, ioaddr + txdp); if (sis900_debug > 1) printf("sis900_transmit: TX descriptor register loaded with: %X\n", inl(ioaddr + txdp)); memcpy(txb, d, ETH_ALEN); memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN); nstype = htons(t); memcpy(txb + 2 * ETH_ALEN, (char*)&nstype, 2); memcpy(txb + ETH_HLEN, p, s); s += ETH_HLEN; s &= DSIZE; if (sis900_debug > 1) printf("sis900_transmit: sending %d bytes ethtype %hX\n", (int) s, t); while (s < ETH_ZLEN) txb[s++] = '\0'; txd.bufptr = (u32) &txb[0]; txd.cmdsts = (u32) OWN | s; outl(TxENA, ioaddr + cr); if (sis900_debug > 1) printf("sis900_transmit: Queued Tx packet size %d.\n", (int) s); to = currticks() + TX_TIMEOUT; while ((((volatile u32) tx_status=txd.cmdsts) & OWN) && (currticks() < to)) ; if (currticks() >= to) { printf("sis900_transmit: TX Timeout! Tx status %X.\n", tx_status); } if (tx_status & (ABORT | UNDERRUN | OWCOLL)) { printf("sis900_transmit: Transmit error, Tx status %X.\n", tx_status); } outl(0, ioaddr + imr); }