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

📄 cs8900if.c

📁 cs8900网络驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
  q = NULL;  switch (htons(ethhdr->type)) {  /* IP packet? */  case ETHTYPE_IP:    /* update ARP table, obtain first queued packet */    q = etharp_ip_input(netif, p);    /* skip Ethernet header */    pbuf_header(p, -14);    LWIP_DEBUGF(NETIF_DEBUG, ("cs8900_input: passing packet up to IP\n"));    /* pass to network layer */    netif->input(p, netif);    break;  /* ARP packet? */  case ETHTYPE_ARP:    /* pass p to ARP module, get ARP reply or ARP queued packet */    q = etharp_arp_input(netif, (struct eth_addr *)&netif->hwaddr, p);    break;  /* unsupported Ethernet packet type */  default:    /* free pbuf */    pbuf_free(p);    p = NULL;    break;  }  /* send out the ARP reply or ARP queued packet */  if (q != NULL) {    /* q pbuf has been succesfully sent? */    if (cs8900_output(netif, q) == ERR_OK)    {      pbuf_free(q);      q = NULL;    }    else    {      /* TODO: re-queue packet in the ARP cache here (?) */      pbuf_free(q);      q = NULL;    }  }}					 /***********************************************************************************************************                       Move a received packet from the cs8900 into a new pbuf.** Description : Must be called after reading an ISQ event containing the*               "Receiver Event" register, before reading new ISQ events.**               This function copies a frame from the CS8900A.*               *               It is designed failsafe:*               - It does not assume a frame is actually present.*               - It checks for non-zero length*               - It does not overflow the frame buffer**                * Arguments   : netif: The lwIP network interface data structure belonging to this device. **********************************************************************************************************/static struct pbuf *cs8900_input(struct netif *netif){  struct pbuf *p = NULL, *q = NULL;  u16_t len = 0;  u16_t event_type;  u16_t i;  u16_t *ptr = NULL;  // read RxStatus  event_type = IORead(CS8900_RxTxDataPort);  // correctly received frame, either broadcast or individual address?  // TODO: maybe defer these conditions to cs8900_input()  if ((event_type & 0x0001U/*RxOK*/) && (event_type & 0x000cU/*Broadcast | Individual*/))  {#if LWIP_SNMP > 0    // update number of received MAC-unicast and non-MAC-unicast packets    if (event_type & 0x0004U/*Individual*/)    {      snmp_inc_ifinucastpkts();    }    else    {      snmp_inc_ifinnucastpkts();    }#endif    event_type = 0;    // read RxLength    len = IORead(CS8900_RxTxDataPort);    len = len>>8 | len << 8;  //the length is register content and therefore needs to be reversed.    LWIP_DEBUGF(NETIF_DEBUG, ("cs8900_input: packet len %u\n", len));    snmp_add_ifinoctets(len);    // positive length?    if (len > 0)    {      // allocate a pbuf chain with total length 'len'      p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);      if (p != NULL)      {        for (q = p; q != 0; q = q->next)	{	  LWIP_DEBUGF(NETIF_DEBUG, ("cs8900_input: pbuf @%p tot_len %u len %u\n", q, q->tot_len, q->len));	  ptr = q->payload;          // TODO: CHECK: what if q->len is odd? we don't use the last byte?          for (i = 0; i < (q->len + 1) / 2; i++)          {            *ptr = IORead(CS8900_RxTxDataPort);            ptr++;          }        }      }      // could not allocate a pbuf      else      {        // skip received frame        // TODO: maybe do not skip the frame at this point in time?        ppWrite(CS_PP_RXCFG, 0x4301U/*SKIP*/);#if (CS8900_STATS > 0)        ((struct cs8900if *)netif->state)->dropped++;#endif        snmp_inc_ifindiscards();        len = 0;      }    }    // length was zero    else    {    }  }  return p;}/***********************************************************************************************************                 Writing an IP packet (to be transmitted) to the CS8900.** Description : Before writing a frame to the CS8900, the ARP module is asked to resolve the*               Ethernet MAC address. The ARP module might undertake actions to resolve the*               address first, and queue this packet for later transmission.*               * Arguments   : netif: The lwIP network interface data structure belonging to this device.*               p pbuf: to be transmitted (or the first pbuf of a chained list of pbufs).*               ipaddr: destination IP address.** Returns     : ERR_OK if the packet was sent or queued. There is no way to*               find out if a packet really makes it onto the network link.* * Notes       : Uses the function cs8900_input() that should handle the actual*               reception of bytes from the network interface.**********************************************************************************************************/err_t cs8900if_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr){  struct cs8900if *cs8900if = netif->state;  err_t result;  /* resolve the link destination hardware address */  p = etharp_output(netif, ipaddr, p);  /* network hardware address obtained? */  if (p != NULL)  {    /* send out the packet */    result = cs8900_output(netif, p);    p = NULL;  }  /* { p == NULL } */  else  {    /* we cannot tell if the packet was sent, the packet could have been queued */    /* on an ARP entry that was already pending. */    return ERR_OK;  }  return result;}							/***********************************************************************************************************                              cs8900_output()** Description : Sends a packet to the cs8900 ethernet controller for transmisison*                * Arguments   : netif: The lwIP network interface data structure belonging to this device. ** Returns     : return error codes*               - ERR_OK: packet transferred to hardware*               - ERR_CONN: no link or link failure*               - ERR_IF: could not transfer to link (hardware buffer full?)***********************************************************************************************************/static err_t cs8900_output(struct netif *netif, struct pbuf *p){  int tries = 0;  err_t result;    // exit if link has failed  if (( ppRead(CS_PP_LINESTATUS) & 0x8000U/*LinkOK*/) != 0x8000U) return ERR_CONN; // no Ethernet link  result = ERR_OK;  /* issue 'transmit' command to CS8900 */  IOWrite(CS_IO_TXCMDW, 0xC900U);//send the write command to the txwrite register    /* send length (in bytes) of packet to send, if its less than the ethernet minimum frame size, the cs8900 will pad automatically */  IOWrite(CS_IO_TXLEN, (p->tot_len<<8 | p->tot_len>>8)); //must be byte reversed! endian issue with the cs8900 auto swapping register data,    // not ready for transmission and still within 100 retries?  while (((ppRead(CS_PP_BUSSTATUS) & 0x0001U/*Rdy4TxNOW*/) != 0x0001) && (tries++ < 100))  {    // throw away the last committed received frame (SKIP)    ppWrite(CS_PP_RXCFG, 0x4301U);  }    // ready to transmit?  if (ppRead(CS_PP_BUSSTATUS) & 0x0001U == 0x0001U)  {  	unsigned long sent_bytes = 0;    /* q traverses through linked list of pbuf's     * This list MUST consist of a single packet ONLY */    struct pbuf *q;    for (q = p; q != NULL; q = q->next)    {      u16_t i;      u16_t *ptr = (u16_t *)q->payload;      /* 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; i < q->len; i += 2)      {        /** TODO: this routine assumes 16-bit boundary pbufs... */        IOWrite(CS8900_RxTxDataPort, *ptr++);        sent_bytes += 2;      }    }    #if (CS8900_STATS > 0)    ((struct cs8900if *)netif->state)->sentpackets++;    ((struct cs8900if *)netif->state)->sentbytes += sent_bytes;#endif    snmp_add_ifoutoctets(sent_bytes);  }  else  {    // { not ready to transmit!? }    snmp_inc_ifoutdiscards();    /* return not connected */    result = ERR_IF;  }  return result;}/***********************************************************************************************************                                    ppRead() - reads cs8900 register content** Description : Reads internal cs8900 packet page registers, and returns their content to the *               calling function.               *               * Arguments   : takes in an 8 bit packet page register address, and returns a 16 bit register content.**********************************************************************************************************/static INT16U ppRead(INT16U pp_addr){        INT16U pp_data;	       //data from the cs8900 pp register will be stored here until it can be returned (2 bytes).    											      Data_DDR = 0xffff;               //set the databus to output    Addr_B = CS8900_PP_PTR_PORT;     //load the address of the pp pointer register onto the address bus    Data_B = pp_addr;                //put the address of the internal cs8900 register we wish to read on to the databus        Signal_B &= ~CS8900_WRITE;       //write this data in to the pp pointer port in the cs8900.    Signal_B |= CS8900_WRITE;        //de-activate the write signal            Data_DDR = 0x0000;               //now, set the databus to input    Addr_B = CS8900_PP_DATA_PORT;    //put the address of the pp data port on to the address bus (this is the register where the cs8900 will put the data we requested just above, all we have to do is retrieve it now)        Signal_B &= ~CS8900_READ;        //assert the read signal. This tells the cs8900 to put the data from the pp data register on to the data bus        pp_data = Data_B;                //store the data thats on the address bus into pp_data        Signal_B |= CS8900_READ;         //de-activate the read signal        return pp_data;                  //return the data from the cs8900 pp register we just read to the calling function. }/***********************************************************************************************************                                    ppWrite() - writes cs8900 register content** Description : Writes 16 bit data values in to the cs8900 packet page registers.*               * Arguments   : Takes in a 16 bit packet page register address, and a 16 bit data*               value to be written to that address. Returns nothing.**********************************************************************************************************/static void ppWrite(INT16U pp_addr, INT16U pp_data){  Data_DDR = 0xffff;                //set the databus to output.	Addr_B = CS8900_PP_PTR_PORT;      //load the address of the pp pointer register onto the address bus	Data_B = pp_addr;                 //put the address of the internal cs8900 register we wish to read on to the databus    Signal_B &= ~CS8900_WRITE;        //write this data in to the pp pointer port in the cs8900.	Signal_B |= CS8900_WRITE;         //de-activate the write signal		Addr_B = CS8900_PP_DATA_PORT;     //put the pp data port address on the address bus. (we write the pointer to this register, then the cs8900 internally gets the data from the register and puts in in the pp data port register)	Data_B = pp_data;                 //put the data that we desire to put into the pp register (pp_address) on the databus		  Signal_B &= ~CS8900_WRITE;        //write this data in to the cs8900 pp data port  Signal_B |= CS8900_WRITE;         //de-activate the write signal, the cs8900 should now have pp_data written to the pp register pp_addr}/*********************************************************************************************************** IORead() - reads cs8900 IO mapped Registers - like the frame data port! - not a packet page function!** Description : Reads a 16 bit word from the cs8900 IO data port. - THIS IS NOT A PACKET PAGE PROCEDURE.*               * Arguments   : Takes in an 8 bit IO register address and returns a 16 bit word from that address**********************************************************************************************************/static INT16U IORead(INT8U IO_Reg_Addr){   INT16U IO_Reg_Data;      //store the returned data here until its returned to the calling function.    Data_DDR = 0x0000;                //set the databus to input  Addr_B = IO_Reg_Addr;		          //put the IO register address we wish to read from on to the databus  Signal_B &= ~CS8900_READ;         //assert the read signal. This tells the cs8900 to put the data from the specified address on to the databus.		IO_Reg_Data = Data_B;             //save the returned data from the cs8900 in IO_Data until its returned to the calling function	Signal_B |= CS8900_READ;          //de-activate the read signal.  		return IO_Reg_Data;               //return the 16 bit word from the cs8900 IO Data Register.}/*********************************************************************************************************** IOWrite() - writes cs8900 IO mapped register like the frame data port! - not a packet page function!** Description : Writes 16 bit data values in to the cs8900 packet page registers.*               * Arguments   : Takes in an 8 bit IO register address, and a 16 bit data*               value to be written to that address. Returns nothing.**********************************************************************************************************/static void IOWrite(INT8U IO_Reg_Addr, INT16U IO_Reg_Data){  Data_DDR = 0xffff;                //Set Data bus to OUTPUT	Data_B = IO_Reg_Data;             //put the data we wish to write to the IO mapped register on the Data Bus 	Addr_B = IO_Reg_Addr;             //put the address of the IO mapped register we wish to write to on the address bus	  Signal_B &= ~CS8900_WRITE;        //write this data in to the cs8900 IO Register  OSTimeDly(1);    Signal_B |= CS8900_WRITE;         //de-activate the write signal}

⌨️ 快捷键说明

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