📄 cs8900if.c
字号:
/** @file * * Ethernet network driver for IP *//* * Copyright (c) 2001-2003 Leon Woestenberg <address@hidden> * Copyright (c) 2001-2003 Axon Digital Design B.V., The Netherlands. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * * This file is part of the lwIP TCP/IP stack. * * Author: Leon Woestenberg <address@hidden> * Modified by: Eric Shufro <address@hidden> * * This is a device driver for the Crystal Semiconductor CS8900 * chip in combination with the lwIP stack. * * This is work under development. Please coordinate changes * and requests with Leon Woestenberg <address@hidden> * * The Swedish Institute of Computer Science and Adam Dunkels * are specifically granted permission to redistribute this * source code under any conditions they seem fit. * * A quick function roadmap: * * cs8900_*() are low level, cs8900 hardware specific functions. * These are declared static in the device driver source and * SHOULD NOT need to be called from outside this source. * * cs8900if_*() are the lwIP network interface functions. * * cs8900_init() sets up the cs8900, using its register set. When * using the driver on your particular hardware platform, make sure * the register setups match. * Function is called from cs8900if_init(). * * cs8900_input() transfers a received packet from the chip. * Function is called from cs8900if_input(). * * cs8900_output() transfers a packet to the chip for transmission. * Function is called from cs8900if_output(). * * cs8900if_init() initializes the lwIP network interface, and * calls cs8900_init() to initialize the hardware. * Function is called from lwIP. * * cs8900if_input() calls cs8900_input() to get a received packet * and then forwards the packet to protocol(s) handler(s). * Function is called from cs8900_service(). * * cs8900if_output() resolves the hardware address, then * calls cs8900_output() to transfer the packet. * Function is called from lwIP. */#include "lwip/opt.h"#include "lwip/def.h"#include "lwip/err.h"#include "lwip/mem.h"#include "lwip/pbuf.h"#include "lwip/stats.h"#include "lwip/sys.h"#include "netif/etharp.h"#include "netif/cs8900if.h"#include "bsp.h"/*********************************************************************************************************** global variables**********************************************************************************************************/ OS_EVENT *CS8900_Service_Sem;extern OS_CPU_SR cpu_sr;/*********************************************************************************************************** Initialize the CS8900 Ethernet MAC/PHY and its device driver.** Description : Initialize the CS8900 interface and then call the low level hardware initializing* function to setup the ethernet controller.* * Arguments : netif: The lwIP network interface data structure belonging to this device.* MAY be NULL as we do not support multiple devices yet.**********************************************************************************************************/err_t cs8900if_init(struct netif *netif){ struct cs8900if *cs8900if; cs8900if = mem_malloc(sizeof(struct cs8900if)); if (cs8900if == NULL) { LWIP_DEBUGF(NETIF_DEBUG, ("cs8900_input: out of memory for cs8900if\n")); return ERR_MEM; } // initialize lwip network interface netif->name[0] = IFNAME0; netif->name[1] = IFNAME1; // set the interface's mac address netif->hwaddr[0] = 0x00; netif->hwaddr[1] = 0x50; netif->hwaddr[2] = 0xc2; netif->hwaddr[3] = 0x25; netif->hwaddr[4] = 0x60; netif->hwaddr[5] = 0x0b; /* downward functions */ netif->output = cs8900if_output; netif->linkoutput = cs8900_output; // initialize cs8900 specific interface state data pointer netif->state = cs8900if; /* maximum transfer unit */ netif->mtu = 1500; /* broadcast capability */ netif->flags = NETIF_FLAG_BROADCAST; /* hardware address length */ netif->hwaddr_len = 6; // initially assume no ISQ event cs8900if->needs_service = 0; // set to 1 if polling method is used cs8900if->use_polling = 0;#if (CS8900_STATS > 0) // number of interrupt service routine calls cs8900if->interrupts = 0; cs8900if->missed = 0; cs8900if->dropped = 0; cs8900if->sentpackets = 0; cs8900if->sentbytes = 0;#endif // intialize the cs8900a chip return cs8900_init();}/*********************************************************************************************************** cs8900_init()** Description : Calls for a CS8900 hardware reset and then initializes the cs8900 registers* * Arguments : netif: The lwIP network interface data structure belonging to this device. ** Returns : return error codes* - ERR_OK: packet transferred to hardware***********************************************************************************************************/static err_t cs8900_init(void){ CS8900_Service_Sem = OSSemCreate(0); /* semaphore to awaken the cs8900 service routine after an isr occurs */ while((cs8900_reset() & 0x8000) != 0x8000) { // if device is not ready...(initd should be set when ready) //todo add timeout OSTimeDly(10); } ppWrite(CS_PP_INTNUM, 0x0000U); //set the cs8900 interrupt to use to pin cs8900 pin 0, (connected to 9s12 micro using IRQ pin) ppWrite(CS_PP_RXCFG, 0x0301U); //receiver configuration register ppWrite(CS_PP_RXCTL, 0x050DU); //receiver control register ppWrite(CS_PP_BUFCFG, 0x0B05U); //bus configuration register ppWrite(CS_PP_BUSCTL, 0x1780U); //bus control register ppWrite(CS_PP_LINECTL, 0xD300U); //line control register ppWrite(CS_PP_IA1, 0x0050U); //mac address high bytes ppWrite(CS_PP_IA2, 0xC225U); //mac address middle bytes ppWrite(CS_PP_IA3, 0x600BU); //mac address low bytes INTCR = 0x40; //re-enable the irq pin now the the cs8900 is ready to go return ERR_OK;}/*********************************************************************************************************** Reset the CS8900A using a hardware reset** Description : Pulls the CS8900's reset pin high to reset the ethernet controller.* * Arguments : None* Notes : Not User Accessible. **********************************************************************************************************/static INT16U cs8900_reset(void){ //default state for the signal bus (no inputs asserted) Signal_B = 0x06; /* pull reset pin and wait a bit */ Signal_B |= CS8900_RESET; OSTimeDly(10); /* release reset pin and wait a bit*/ Signal_B &= ~CS8900_RESET; OSTimeDly(10); //toggle SBHE to enter 16 bit mode (as specified in the datasheet) Signal_B |= CS8900_SBHE; //SBHE active OSTimeDly(10); Signal_B &= ~CS8900_SBHE; //SBHE inactive OSTimeDly(10); Signal_B |= CS8900_SBHE; //SBHE active OSTimeDly(10); Signal_B &= ~CS8900_SBHE; //SBHE inactive OSTimeDly(10); //return the value of the selftest register which tells us if the device has finished resetting return ppRead(CS_PP_SELFTEST); }/*********************************************************************************************************** CS8900 Interrupt Service Routine** Description : function which gets called after the cs8900 asserts a hardware interrupt * this posts a semaphore to the OS in order to awaken ServiceCS8900 which * actually does the dirty work. The hardware interrupt pin is disabled here as well.* * Arguments : None**********************************************************************************************************/void CS8900_Interrupt(void) { INT8U err; INT16U isq_data; //hold the isq event register number INTCR = 0x00; //disable the irq pin! /* do { isq_data = IORead(CS8900_ISQ) >> 8; switch(isq_data & 0x3f) { case 0x00: //isq is empty. exit. break; case 0x04: //receieve event cs8900if_input(&netif); break; case 0x08: //transmit event break; case 0x0C: //buffer event break; case 0x10: //receiver miss event break; case 0x12: //transmit collision event break; default: //should never be here event. break; } }while(isq_data != 0); */ err = OSSemPost(CS8900_Service_Sem); //signal ServiceCS8900 to run. }/*********************************************************************************************************** CS8900 Service Routine** Description : function which gets called after the cs8900 interrupt routine runs and posts a * semaphore to awaken this task and service the cs8900 ISQ and get data etc...* When done servicing the cs8900, the hardware interrupt pin is re-enabled.* * Arguments : None**********************************************************************************************************/void ServiceCS8900(void){ INT8U err; INT16U isq_data; //hold the isq event register number while(1) { OSSemPend(CS8900_Service_Sem, 0, &err); do { isq_data = IORead(CS8900_ISQ) >> 8; switch(isq_data & 0x3f) { case 0x00: //isq is empty. exit. break; case 0x04: //receieve event cs8900if_input(&netif); break; case 0x08: //transmit event break; case 0x0C: //buffer event break; case 0x10: //receiver miss event break; case 0x12: //transmit collision event break; default: //should never be here event. break; } }while(isq_data != 0); INTCR = 0x40; //re-enable interrupts }} /*********************************************************************************************************** Read a received packet from the CS8900.** Description : This function should be called when a packet is received by the CS8900* and is fully available to read. It moves the received packet to a pbuf* which is forwarded to the IP network layer or ARP module. It transmits* a resulting ARP reply or queued packet.* * Arguments : netif: The lwIP network interface to read from.* * Notes : Uses cs8900_input() to move the packet from the CS8900 to a* newly allocated pbuf.**********************************************************************************************************/void cs8900if_input(struct netif *netif){ struct cs8900if *cs8900if = netif->state; struct eth_hdr *ethhdr = NULL; struct pbuf *p = NULL, *q = NULL; /* move received packet into a new pbuf */ p = cs8900_input(netif); /* no packet could be read */ if (p == NULL) { /* silently ignore this */ return; } /* points to packet payload, which starts with an Ethernet header */ ethhdr = p->payload;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -