⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 et9000if.c

📁 DM9000A some kinda source codes that might help
💻 C
📖 第 1 页 / 共 2 页
字号:
	hash_table[3] = 0x8000;

	/* the multicast address in Hash Table : 64 bits */
	for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
		hash_val = cal_CRC((unsigned char *)mcptr->dmi_addr, 6, 0) & 0x3f; 
		hash_table[hash_val / 16] |= (u16_t) 1 << (hash_val % 16);
	}

	/* Write the hash table to MAC MD table */
	for (i = 0, oft = 0x16; i < 4; i++) {
		iow(oft++, hash_table[i] & 0xff);
		iow(oft++, (hash_table[i] >> 8) & 0xff);
	}
}

static void dm9000XmitDone(Dm9000if_t *db)
{
//		int tx_status = ior(0x01);	/* Got TX status */
		
//		if (tx_status & 0xc) {
			/* One packet sent complete */
		db->tx_pkt_cnt--;
		// Queue packet check & send 
		if (db->tx_pkt_cnt > 0) {
			iow(0xfc, db->queue_pkt_len & 0xff);
			iow(0xfd, (db->queue_pkt_len >> 8) & 0xff);
			iow(0x2, 0x1);
		}

//		}
}



// DM9000 NIC low level functions___________________________________________________

static void dm9000Interrupt(Dm9000if_t *ethernetif)
{
	int status;
	u8_t savedReg;

	// Save previous register address
	savedReg = inb(DM9000_INDEX);

	// Disable all interrupt
	iow(0xff, 0x80); 

	// Got DM9000 interrupt status
	status = ior(0xfe);		// Got ISR
	iow(0xfe, status);		// Clear ISR status 

  
	// Received the coming packet
	if (status & DM9000_RX_INTR) {
    if (ethernetif->rxEmpty) {
      ethernetif->rxEmpty = 0; 
	    QPut(THREAD_LWIP, MSGPRIO_NORMAL, MSG_ETH_RECEIVE, 0);
    }
  }

	// Transmit Interrupt check
	if (status & DM9000_TX_INTR) {
		dm9000XmitDone(ethernetif);
//		QPut(THREAD_LWIP, MSGPRIO_NORMAL, MSG_ETH_TRANSMIT, 0);
    }
		
	// Re-enable interrupt mask 
	iow(0xff, 0x83);

	// Restore previous register address
	outb(savedReg, DM9000_INDEX); 
}

static void dm9000if_low_level_init(struct netif *netif)
{
    int i;
    u8_t io_mode;
	Dm9000if_t *ethernetif = (Dm9000if_t *)netif->state;
	
	//set MAC hardware address length
	netif->hwaddr_len = 6;
	
	// set MAC hardware address
  for(i = 0; i < 6; i++)
	  ethernetif->ethaddr.addr[i] =sys.mac[5 - i];
	memcpy(netif->hwaddr, ethernetif->ethaddr.addr, netif->hwaddr_len);
	
	// maximum transfer unit
	netif->mtu = 1500;
	
	// broadcast capability
	netif->flags = NETIF_FLAG_BROADCAST;
 
	/* RESET device */
	iow(0, 1);
	udelay(100);			  /* delay 100us */

	/* Probe the board */
	dmfe_probe(ethernetif);
	
	/* I/O mode */
	io_mode = ior(0xfe) >> 6; /* ISR bit7:6 keeps I/O mode */

	/* NIC Type: FASTETHER, HOMERUN, LONGRUN */
	identify_nic(ethernetif);	

	/* GPIO0 on pre-activate PHY */
	iow(0x1f,0x00); 		/*REG_1F bit0 activate phyxcer*/

	/* Set PHY */
	ethernetif->op_mode = media_mode;
	set_PHY_mode(ethernetif);

	/* Program operating register */
	iow(0x00, DM9000_REG00);
	iow(0x02, 0);			/* TX Polling clear */
	iow(0x08, 0x3f);		/* Less 3Kb, 200us */
	iow(0x09, DM9000_REG09);	/* Flow Control : High/Low Water */
	iow(0x0a, DM9000_REG0A);	/* Flow Control */
	iow(0x2f, 0);			/* Special Mode */
	iow(0x01, 0x2c);		/* clear TX status */
	iow(0xfe, 0x0f); 		/* Clear interrupt status */
 
	/* Set address filter table */
	dm9000_hash_table(ethernetif);

	/* Init Driver variable */
	ethernetif->link_failed = 1;
	ethernetif->tx_pkt_cnt = 0;
	ethernetif->queue_pkt_len = 0;
	ethernetif->rxEmpty = 1;

	/* Set MAC address variable */
  
	for (i = 0; i < 6; i++) 
        iow((0x10 + i), ethernetif->ethaddr.addr[i]);
  
  
	/*  Registry_interrupt */
	at91RegisterInterrupt(IRQ_NIC, (void *)dm9000Interrupt, ethernetif);
	at91.pio->PIO_PDR = PIOIRQ0;
	at91.aic->AIC_SMR[IRQ_NIC] = AIC_SRCTYPE_INT_HIGH_LEVEL_SENSITIVE;
	at91.aic->AIC_IECR = AIC_IRQ0;

	/* Activate DM9000 */
	iow(0x05, DM9000_REG05 | 1);	/* RX enable */
	iow(0xff, DM9000_REGFF);    	/* Enable TX/RX interrupt mask */
  
    //dump(Set.lgp, (void *)0x30000fe, 2);
}

static err_t dm9000if_low_level_output(struct netif *netif, struct pbuf *p)
{
	int i;
    struct pbuf *q;
    u8_t *pdata, *pbuff;
    u8_t buffer[1024];
	Dm9000if_t *ethernetif = (Dm9000if_t *)netif->state;

	while (ethernetif->tx_pkt_cnt > 1); 
	
	// Disable all interrupt
	iow(0xff, 0x80);
	
	// Move data to DM9000 TX RAM
	outb(0xf8, DM9000_INDEX);
	
	// Word mode
	pbuff = buffer;
 	for (q = p; q != NULL; q = q->next) {
   		// Send the data from the pbuf to the interface, one pbuf at a
   		// time. The size of the data in each pbuf is kept in the ->len
   		// variable.
   	    for (i = 0, pdata = (u8_t *)q->payload; i < q->len; i++) 
            *pbuff++ = *pdata++; 
	}
    outsw((u16_t *)buffer, p->tot_len);

	// TX control: First packet immediately send, second packet queue
	if (ethernetif->tx_pkt_cnt == 0) {
		
		// First Packet
		ethernetif->tx_pkt_cnt++;

		// Set TX length to DM9000 
		iow(0xfc, p->tot_len & 0xff);
		iow(0xfd, (p->tot_len >> 8) & 0xff);

		// Issue TX polling command
		iow(0x2, 0x1);		// Cleared after TX complete 

	}
    else {
		// Second packet
		ethernetif->tx_pkt_cnt++;
		ethernetif->queue_pkt_len = p->tot_len;
	}
 
  lwip_stats.link.xmit++;
 
	// Re-enable resource check 
//	if (ethernetif->tx_pkt_cnt == 1)
//    	; 
		
	// Re-enable interrupt 
	iow(0xff,0x83);
	
	return 0;
}

static struct pbuf *dm9000if_low_level_input(struct netif *netif)
{
	u8_t rxbyte;
	u16_t i, RxStatus, RxLen, GoodPacket, tmplen, len;
    struct pbuf *p;
    struct pbuf *q;
	Dm9000if_t *ethernetif = (Dm9000if_t *)netif->state;
   
	// Disable all interrupt
	iow(0xff, 0x80);
    
	ior(0xf0);			// Dummy read
	rxbyte = inb(DM9000_DATA);	// Got most updated data

	// Status check: this byte must be 0 or 1
	if (rxbyte > DM9000_PKT_RDY) {
		iow(0xff, 0x80);	// Stop INT request
		iow(0xfe, 0x80);	// Clear ISR status
		iow(0x05, 0x00);	// Stop Receive
		ethernetif->device_wait_reset = true; 
		ethernetif->reset_rx_status++;
	}

	// packet ready to receive check 
	if (rxbyte == DM9000_PKT_RDY) {
    // Re-enable interrupt 
    iow(0xff,0x83);
        
  	// A packet ready now  & Get status/length
		GoodPacket = true;
		outb(0xf2, DM9000_INDEX);
			
		// Word mode
   	RxStatus = inw(DM9000_DATA);
		RxLen    = inw(DM9000_DATA);
	
    // Packet Status check
    if (RxLen < 0x40) { 
		  GoodPacket = false; 
		  ethernetif->runt_length_counter++; 
    }
    if (RxLen > DM9000_PKT_MAX) { 
		  ethernetif->device_wait_reset = true; 
  	  ethernetif->long_length_counter++; 
	  }
	  if (RxStatus & 0xbf00) {
		  GoodPacket = false;
    }
		// Move data from DM9000
    if (!ethernetif->device_wait_reset) {    
	    if (GoodPacket && ((p = pbuf_alloc(PBUF_LINK, RxLen, PBUF_POOL)) != NULL ) ) {	
		    // Read received packet from RX SARM, Word mode
		    tmplen = (RxLen + 1) / 2;
        // We iterate over the pbuf chain until we have read the entire packet into the pbuf.
   	    for (q = p; q != NULL; q = q->next) {                   
          // Read enough bytes to fill this pbuf in the chain. The avaliable data in the pbuf is given by the q->len variable.                               
      
          if (RxLen < q->len)
            len = RxLen;
          else
       	    len = q->len;
        
          insw((u16_t *)q->payload, len);
          RxLen -=len;
        } 
        return p;
		  } 
      else {
			  // Without buffer or error packet, Word mode
   	    len = (RxLen + 1) / 2;
	      for (i = 0; i < len; i++)
	        inw(DM9000_DATA);
        lwip_stats.link.drop++;
      }
    }
    else // device_wait_reset
      if(ethernetif->device_wait_reset)
        dm9000if_low_level_init(netif);
  }
//    } while (rxbyte == DM9000_PKT_RDY && !db->device_wait_reset);

  ethernetif->rxEmpty = 1; 
  // Re-enable interrupt 
  iow(0xff,0x83);
  return NULL;
}


/*-----------------------------------------------------------------------------------*/
/*
 * dm9000_output():
 *
 * This function is called by the TCP/IP stack when an IP packet
 * should be sent. It calls the function called low_level_output() to
 * do the actuall transmission of the packet.
 *
 */
/*-----------------------------------------------------------------------------------*/
err_t dm9000if_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
{
    p = etharp_output(netif, ipaddr, p);
    return dm9000if_low_level_output(netif, p);
}


/*-----------------------------------------------------------------------------------*/
/*
 * dm9000_input():
 *
 * This function should be called when a packet is ready to be read
 * from the interface. It uses the function low_level_input() that
 * should handle the actual reception of bytes from the network
 * interface.
 *
 */
/*-----------------------------------------------------------------------------------*/
void dm9000if_input(struct netif *netif)
{
    Dm9000if_t *ethernetif = netif->state;
    struct eth_hdr *ethhdr;
    struct pbuf *p;

    lwip_stats.link.recv++;
    
    while ((p = dm9000if_low_level_input(netif))) {

        ethhdr = p->payload;
    
        switch (htons(ethhdr->type)) {
    
        case ETHTYPE_IP:
    		etharp_ip_input(netif, p);
    		pbuf_header(p, -14);
    		netif->input(p, netif);
    		break;
            
        case ETHTYPE_ARP:
    		p = etharp_arp_input(netif, &ethernetif->ethaddr, p);
    		if (p != NULL) {
    			dm9000if_low_level_output(netif, p);
    			pbuf_free(p);
    		}
    		break;
            
        default:
    		pbuf_free(p);
    		break;
    }
  }
}

/*-----------------------------------------------------------------------------------*/
/*
 * dm9000_init():
 *
 * Should be called at the beginning of the program to set up the
 * network interface. It calls the function low_level_init() to do the
 * actual setup of the hardware.
 *
 */
/*-----------------------------------------------------------------------------------*/
err_t dm9000if_init(struct netif *netif)
{
    netif->name[0] = 'e';
    netif->name[1] = 't';
    netif->output = dm9000if_output;
    netif->linkoutput = dm9000if_low_level_output;
  
    dm9000if_low_level_init(netif);
    etharp_init();
    return ERR_OK;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -