Ejemplo n.º 1
0
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;
	}
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
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);

}
Ejemplo n.º 4
0
/* 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;
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
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
}
Ejemplo n.º 8
0
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');
    }
}
Ejemplo n.º 9
0
Archivo: retry.c Proyecto: 3a9LL/panda
/**
 * 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 );
}
Ejemplo n.º 10
0
Archivo: retry.c Proyecto: 3a9LL/panda
/**
 * 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 ) );
}
Ejemplo n.º 11
0
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;
}
Ejemplo n.º 12
0
Archivo: retry.c Proyecto: 3a9LL/panda
	      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;
		}
	}
}
Ejemplo n.º 13
0
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;
}
Ejemplo n.º 14
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 ();

}
Ejemplo n.º 15
0
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;
}
Ejemplo n.º 16
0
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
}
Ejemplo n.º 17
0
/**************************************************************************
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;
}
Ejemplo n.º 18
0
static void davicom_wait(unsigned int nticks)
{
  unsigned int to = currticks() + nticks;
  while (currticks() < to)
    /* wait */ ;
}
Ejemplo n.º 19
0
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;
}
Ejemplo n.º 20
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);
}
Ejemplo n.º 21
0
Archivo: 3c515.c Proyecto: 3a9LL/panda
static void t3c515_wait(unsigned int nticks)
{
	unsigned int to = currticks() + nticks;
	while (currticks() < to)
		/* wait */ ;
}
Ejemplo n.º 22
0
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);
}