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

📄 cs8900if.c

📁 LwIP adaptation for Fujitsu MB90f497 and CS8900A Ethernet driver
💻 C
📖 第 1 页 / 共 2 页
字号:
// cs8900a whether it needs service.////// As such, may be used robustly called as a deferred// (or "late") interrupt handler, or may be called in// a loop to implement polling, or both.//// Use cs8900if_service() from your application instead// of this function.static void cs8900_service(struct netif *netif){  // amount of ISQ's to handle (> 0) in one cs8900_service() call  unsigned char events2service = 1;  // NOTES:  // static, so only initialized to zero at program start.  // irq_status will always hold the last ISQ event register that  // still needs service. As such, we may leave this function if  // we encounter an event we cannot service yet, and return later  // to try to service it.  static u16_t irq_status = 0x0000U;  // The "cs8900_needs_service" flag indicates whether any events  // still need to be serviced.  // clear flag here.  // a receive interrupt can, *concurrently with this function*,  // set this flag on new ISQ event occurences.  // we will re-evaluate the correct setting of this flag at  // function exit (below).  ((struct cs8900if *)netif->state)->needs_service = 0;    // no unhandled irq_status left?  if (irq_status == 0x0000U)  {    // read ISQ register    irq_status = ISQ;  }  // ISQ interrupt event, and allowed to service in this loop?  while ((irq_status != 0x0000U) && (events2service-- > 0))  {    // investigate event    if ((irq_status & 0x003fU) == 0x0004U/*Receiver Event*/)    {      // correctly received frame, either broadcast or individual address      // TODO: think where these checks should appear: here or in cs8900_input()      if ((irq_status & 0x0100U/*RxOK*/) && (irq_status & 0x0c00U/*Broadcast | Individual*/))      {        // read the frame from the cs8900a        cs8900if_input(netif);      }      else      {        // skip this frame        PACKETPP = CS_PP_RXCFG;        PPDATA |= 0x0040U/*Skip_1*/;#if (CS8900_STATS > 0)        ((struct cs8900if *)netif->state)->dropped++;#endif      }    }#if (CS8900_STATS > 0)    else if ((irq_status & 0x003fU) == 0x0010U/*RxMISS Event*/)    {  	  ((struct cs8900if *)netif->state)->missed += (irq_status >> 6);  	}    else if ((irq_status & 0x003fU) == 0x0012U/*TxCOL Event*/)    {  	  ((struct cs8900if *)netif->state)->collisions += (irq_status >> 6);  	}#endif    // read ISQ register    irq_status = ISQ;  }  // we did not deplete the ISQ?  if (irq_status != 0x0000U)  {    // the cs8900a still needs service    ((struct cs8900if *)netif->state)->needs_service = 1;  }#if (CS8900_STATS > 1)  // read RxMiss Counter (zeroes itself upon read)  PACKETPP = CS_PP_RXMISS;  ((struct cs8900if *)netif->state)->missed += (PPDATA >> 6);  // read RxCol Counter (zeroes itself upon read)  PACKETPP = CS_PP_TXCOL;  ((struct cs8900if *)netif->state)->collisions += (PPDATA >> 6);#endif}void cs8900if_service(struct netif *netif){  // is there a reason to call the service routine?  if ((((struct cs8900if *)netif->state)->needs_service) || (((struct cs8900if *)netif->state)->use_polling))  {    cs8900_service(netif);  }}/*-----------------------------------------------------------------------------------*//* * cs8900if_output(): * * This function is called by the TCP/IP stack when an IP packet * should be sent. After ARP address lookup, it calls cs8900_output() to * do the actual transmission of the packet. * *//*-----------------------------------------------------------------------------------*/static err_tcs8900if_output(struct netif *netif, struct pbuf *p,		  struct ip_addr *ipaddr){  struct cs8900if *cs8900if = netif->state;  struct pbuf *q = NULL;  struct eth_hdr *ethhdr;  struct eth_addr *dest, mcastaddr;  struct ip_addr *queryaddr;    struct pbuf *r;  err_t err;  u8_t i;  /* Make room for Ethernet header. */  if(pbuf_header(p, 14) != 0) {    /* The pbuf_header() call shouldn't fail, but we allocate an extra       pbuf just in case. */    q = pbuf_alloc(PBUF_LINK, 14, PBUF_RAM);    if(q == NULL) {      return ERR_MEM;    }    pbuf_chain(q, p);    p = q;  }  /* Construct Ethernet header. Start with looking up deciding which     MAC address to use as a destination address. Broadcasts and     multicasts are special, all other addresses are looked up in the     ARP table. */  queryaddr = ipaddr;  if(ip_addr_isany(ipaddr) ||     ip_addr_isbroadcast(ipaddr, &(netif->netmask))) {    dest = (struct eth_addr *)&ethbroadcast;  } else if(ip_addr_ismulticast(ipaddr)) {    /* Handle multicast MAC address hashing. */    mcastaddr.addr[0] = 0x01;    mcastaddr.addr[1] = 0x00;    mcastaddr.addr[2] = 0x5e;    mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;    mcastaddr.addr[4] = ip4_addr3(ipaddr);    mcastaddr.addr[5] = ip4_addr4(ipaddr);    dest = &mcastaddr;  } else {    if(ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {      /* Use destination IP address if the destination is on the same         subnet as we are. */      queryaddr = ipaddr;    } else {      /* Otherwise we use the default router as the address to send         the Ethernet frame to. */      queryaddr = &(netif->gw);    }    dest = arp_lookup(queryaddr);  }  /* If the arp_lookup() didn't find an address, we send out an ARP     query for the IP address. */  if(dest == NULL) { /*     	Put_String("Call:");	mprintf((float)stats.mem.used,6,0);	Put_String(" \n");*/    r = arp_query(netif, ((struct cs8900if *)netif->state)->ethaddr, queryaddr);/*      	Put_String("Arp_querry:");	mprintf((float)stats.mem.used,6,0);	Put_String(" \n");*/    if(r != NULL) {      err = cs8900_output(netif, r);#if defined(CS8900_TX_QUEUE) && (CS8900_TX_QUEUE > 0)      // a rather stupid attempt to queue packets during ARP resolution      // arp request sent?      if (err == ERR_OK)			{			  // enqueue packet        if (((struct cs8900if *)netif->state)->tx_queue == NULL)          ((struct cs8900if *)netif->state)->tx_queue = p;				return ERR_OK;			}#else      pbuf_free(r);      return err;#endif    }    return ERR_MEM;  }  ethhdr = p->payload;  for(i = 0; i <  6; i++) {    ethhdr->dest.addr[i] = dest->addr[i];    ethhdr->src.addr[i] = ((struct cs8900if *)netif->state)->ethaddr->addr[i];  }  ethhdr->type = htons(ETHTYPE_IP);  err = cs8900_output(netif, p);  // we allocated the ethernet header ourselves  // dechain it from the original pbuf  // then free it  if (q != NULL)  {    pbuf_dechain(q);    pbuf_free(q);  }/*      	Put_String("After:");	mprintf((float)stats.mem.used,6,0);	Put_String(" \n");*/  return err;}/*-----------------------------------------------------------------------------------*//* * cs8900if_input(): * * This function should be called when a packet is ready to be read * from the interface. It uses the function cs8900_input() that * should handle the actual reception of bytes from the network * interface. * *//*-----------------------------------------------------------------------------------*/static voidcs8900if_input(struct netif *netif){  struct cs8900if *cs8900if = netif->state;  struct eth_hdr *ethhdr;  struct pbuf *p;  p = cs8900_input(netif);  if(p == NULL) {    return;  }  ethhdr = p->payload;  switch(htons(ethhdr->type)) {  case ETHTYPE_IP:/*  Put_String("cs8900if_input: ip-pack ");  pbuf_free(p); */    arp_ip_input(netif, p);    pbuf_header(p, -14);    netif->input(p, netif);    break;  case ETHTYPE_ARP:    p = arp_arp_input(netif, ((struct cs8900if *)netif->state)->ethaddr, p);    if(p != NULL) {      cs8900_output(netif, p);      pbuf_free(p);    }#if defined(CS8900_TX_QUEUE) && (CS8900_TX_QUEUE > 0)    // this could have been an ARP reply    // possible resolving a queued packet destination address    else		{		  if (((struct cs8900if *)netif->state)->tx_queue)			{        struct eth_addr *dest;        struct ip_hdr *iphdr;        // point to IP header        pbuf_header(((struct cs8900if *)netif->state)->tx_queue, -14);				iphdr = ((struct cs8900if *)netif->state)->tx_queue->payload;        // point to link header        pbuf_header(((struct cs8900if *)netif->state)->tx_queue, 14);				// address can now be resolved?        if ((dest = arp_lookup(&(iphdr->dest))))				{				  char i;          ethhdr = ((struct cs8900if *)netif->state)->tx_queue->payload;          for(i = 0; i < 6; i++)          {            ethhdr->dest.addr[i] = dest->addr[i];            ethhdr->src.addr[i] = ((struct cs8900if *)netif->state)->ethaddr->addr[i];					}          ethhdr->type = htons(ETHTYPE_IP);          cs8900_output(netif, ((struct cs8900if *)netif->state)->tx_queue);        }				((struct cs8900if *)netif->state)->tx_queue = NULL;			}		}#endif    break;  default:    pbuf_free(p);    break;  }}/*-----------------------------------------------------------------------------------*//* * cs8900if_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. * *//*-----------------------------------------------------------------------------------*/voidcs8900if_init(struct netif *netif){  struct cs8900if *cs8900if;  // TODO: check result!  cs8900if = mem_malloc(sizeof(struct cs8900if));	if (cs8900if == NULL) return;  netif->state = cs8900if;  netif->name[0] = IFNAME0;  netif->name[1] = IFNAME1;  netif->output = cs8900if_output;  netif->linkoutput = cs8900_output;  cs8900if->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);  // initially assume no ISQ event  cs8900if->needs_service = 0;  // set to 1 if polling method is used  cs8900if->use_polling = 1;#if (CS8900_STATS > 0)  // number of interrupts (vector calls)  cs8900if->interrupts = 0;  cs8900if->missed = 0;  cs8900if->dropped = 0;  cs8900if->sentpackets = 0;  cs8900if->sentbytes = 0;#endif  cs8900_init(netif);  // TODO: remove this hack  cs8900if_netif = netif;  arp_init();}/*-----------------------------------------------------------------------------------*/// this basically dumps a array of bytes, length "len" into a UDP message. It bypasses// any functionality within lwIP, acting as a low level debug output function (in case// your hardware has no, or limited, display output available) to debug lwIP itself.//// The checksum routines are not implemented yet here, so do not expect your target's// IP stack to accept this packet. It works great, however, in combination with a//  packet snooper, such as Ethereal (www.ethereal.org).//void cs8900_send_debug(unsigned char *p, unsigned int len){	int tries = 0, i;  // exit if link has failed  PACKETPP = CS_PP_LINESTATUS;  if ((PPDATA & 0x0080U/*LinkOK*/) == 0) return; // TODO: find a correct error code  /* transmit command */  TXCMD = 0x00C9U;  TXLENGTH = (14 + 20 + 8 + len < 60)?60:(14 + 20 + 8 + len);  PACKETPP = CS_PP_BUSSTATUS;  // not ready for transmission and still within 100 retries?  while(((PPDATA & 0x0100U/*Rdy4TxNOW*/) == 0) && (tries++ < 100))  {    // throw away the last committed received frame    PACKETPP = CS_PP_RXCFG;    PPDATA = (0x0003U | 0x0040U/*Skip_1*/ | 0x0100U/*RxOKiE*/);    PACKETPP = CS_PP_BUSSTATUS;    /* cs8900if->dropped++; CHECK: we do not know if we actually will drop a frame here, do we? */  }  // ready to transmit?  if((PPDATA & 0x0100U/*Rdy4TxNOW*/) != 0)  {    // destination Ethernet address    RXTXREG = 0xffff;//htons((0x00 << 8) | 0x0a);    RXTXREG = 0xffff;//htons((0x24 << 8) | 0xc5);    RXTXREG = 0xffff;//htons((0x72 << 8) | 0x6d);    // source Ethernet address    RXTXREG = htons(((u16_t)ETHADDR0 << 8U) | (u16_t)ETHADDR1);    RXTXREG = htons(((u16_t)ETHADDR2 << 8U) | (u16_t)ETHADDR3);    RXTXREG = htons(((u16_t)ETHADDR4 << 8U) | (u16_t)ETHADDR5);    // frame type    RXTXREG = htons(0x0800);    // TOS, version    RXTXREG = htons(((0x40 | 0x05) << 8) | 0x00);    // length    RXTXREG = htons(20 + 12 + len);    // identifier    RXTXREG = htons(0);    // fragment offset    RXTXREG = htons(0);    // TTL, UDP protocol    RXTXREG = htons((255U << 8) | 17U);    // checksum    RXTXREG = htons(0);    // source IP    RXTXREG = htons((htonl(cs8900if_netif->ip_addr.addr) & 0xffff0000U) >> 16);    // source IP    RXTXREG = htons(htonl(cs8900if_netif->ip_addr.addr) & 0x0000ffffU);    // destination IP    RXTXREG = htons(0xc0a8);    // destination IP    RXTXREG = htons(0x0001);    // source port 3000    RXTXREG = htons(3000);    // destination port 3000    RXTXREG = htons(3000);    // UDP length    RXTXREG = htons(len);    // UDP checksum    RXTXREG = htons(0);    for (i = 0; i < len; i += 2)    {      RXTXREG = htons((p[i] << 8) | p[i + 1]);    }		while (i < 60)		{      RXTXREG = 0;			i += 2;		}  }}

⌨️ 快捷键说明

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