add modbus slave support

add modbus slave support
This commit is contained in:
Supowang1989
2020-02-24 21:40:06 +08:00
parent 79be128f5f
commit ef82dbfc6d
1129 changed files with 295648 additions and 1776 deletions

View File

@@ -0,0 +1,75 @@
/*
FreeRTOS V4.0.1 - Copyright (C) 2003-2006 Richard Barry.
MCF5235 Port - Copyright (C) 2006 Christian Walter.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FreeRTOS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FreeRTOS; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS, without being obliged to provide
the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details of how and when the exception
can be applied.
***************************************************************************
See http://www.FreeRTOS.org for documentation, latest information, license
and contact details. Please ensure to read the configuration and relevant
port sections of the online documentation.
***************************************************************************
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/*-----------------------------------------------------------
* Application specific definitions.

View File

@@ -0,0 +1,99 @@
#
# FreeModbus MCF5235 port- Makefile
#
# Copyright (c) 2006 Christian Walter, Vienna 2006.
#
# $Id: Makefile,v 1.1 2006/08/30 23:18:06 wolti Exp $
#
# ---------------------------------------------------------------------------
BASE = /opt/gcc-m68k/bin
CC = $(BASE)/m68k-elf-gcc
CXX = $(BASE)/m68k-elf-g++
OBJCOPY = $(BASE)/m68k-elf-objcopy
SIZE = $(BASE)/m68k-elf-size
INSIGHT = $(BASE)/m68k-bdm-elf-insight
BDMFLASH = $(BASE)/bdmflash
#CFLAGS = -MD -O2 -m528x -Wall
MB_INC = -Iport -I../../modbus/tcp -I../../modbus/include
RTOS_INC = -Ifreertos/include -I../Common/include
LWIP_INC = -Ilwip/src/include -Ilwip/src/include/ipv4 \
-Ilwip/src/include -Ilwip/src/include/ipv4 \
-Ilwip/contrib/port/FreeRTOS/MCF5235 \
-Ilwip/contrib/port/FreeRTOS/MCF5235/netif
CFLAGS = -MD -gdwarf-2 -g3 -m528x -Wall \
-D'GCC_MCF5235=1' -D'_GCC_USES_FP=1' \
-D'__IPSBAR=((vuint8 *) 0x40000000)' -D'FSYS_2=25000000UL'
CFLAGS += -I. -Iinclude -Iinclude/arch $(RTOS_INC) $(MB_INC) $(LWIP_INC)
ASFLAGS = -MD -gdwarf-2 -g3 -m528x -Wa,--register-prefix-optional \
-Wa,--bitwise-or -Wa,--defsym,IPSBAR=0x40000000
LDSCRIPT = m5235-ram.ld
LDFLAGS = -nostartfiles -m528x -Wl,--script=$(LDSCRIPT)
TGT = demo
OTHER_CSRC =
OTHER_ASRC = $(addprefix system/, crt0.S vector.S)
MB_SRC = $(addprefix ../../modbus/, mb.c tcp/mbtcp.c functions/mbfunccoils.c functions/mbfuncdiag.c functions/mbfuncholding.c functions/mbfuncinput.c functions/mbfuncother.c functions/mbfuncdisc.c functions/mbutils.c) \
$(addprefix port/, porttcp.c portevent.c portother.c )
CSRC = demo.c $(MB_SRC) \
$(addprefix system/, init.c newlib.c serial.c) \
$(addprefix freertos/, tasks.c queue.c list.c) \
$(addprefix freertos/portable/MemMang/, heap_3.c) \
$(addprefix freertos/portable/GCC/MCF5235/, port.c) \
$(addprefix lwip/src/core/, tcp_out.c inet.c mem.c memp.c netif.c pbuf.c raw.c stats.c sys.c tcp.c tcp_in.c udp.c ipv4/ip.c ipv4/ip_addr.c ipv4/icmp.c ipv4/ip_frag.c) \
$(addprefix lwip/src/api/, tcpip.c api_msg.c err.c api_lib.c ) \
$(addprefix lwip/src/netif/, etharp.c ) \
$(addprefix lwip/contrib/port/FreeRTOS/MCF5235/, sys_arch.c netif/fec.c netif/nbuf.c)
ASRC = $(addprefix system/, mcf5xxx.S )
OBJS = $(CSRC:.c=.o) $(ASRC:.S=.o)
NOLINK_OBJS = $(OTHER_CSRC:.c=.o) $(OTHER_ASRC:.S=.o)
DEPS = $(OBJS:.o=.d) $(NOLINK_OBJS:.o=.d)
BIN = $(TGT).elf
.PHONY: clean all
all: $(BIN)
flash-programm: $(TGT).elf
$(OBJCOPY) -O binary $(TGT).elf $(TGT).bin
@BIN_SIZE=`du -b $(TGT).bin | awk '//{ print $$1; }'`; \
echo "programming $(TGT).bin with size $$BIN_SIZE to flash..."; \
$(BDMFLASH) /dev/bdmcf20 0x00000000 1 2 write $(TGT).bin 0
flash-verify:
@BIN_SIZE=`du -b $(TGT).bin | awk '//{ print $$1; }'`; \
echo "loading $$BIN_SIZE bytes from target into $(TGT).vrf..."; \
$(BDMFLASH) /dev/bdmcf20 0x00000000 1 2 read $(TGT).vrf 0 $$BIN_SIZE
flash-erase:
$(BDMFLASH) /dev/bdmcf20 0x00000000 1 2 erase
debug:
$(INSIGHT) --command=m5235.gdb --se=$(TGT).elf
$(BIN): $(OBJS) $(NOLINK_OBJS)
$(CC) $(LDFLAGS) -Wl,-Map=$(TGT).map $(OBJS) $(LDLIBS) -o $@
clean:
rm -f $(DEPS)
rm -f $(OBJS) $(NOLINK_OBJS)
rm -f $(BIN) $(TGT).map
# ---------------------------------------------------------------------------
# rules for code generation
# ---------------------------------------------------------------------------
%.o: %.c
$(CC) $(CFLAGS) -o $@ -c $<
%.o: %.S
$(CC) $(ASFLAGS) -o $@ -c $<
# ---------------------------------------------------------------------------
# # compiler generated dependencies
# ---------------------------------------------------------------------------
-include $(DEPS)

View File

@@ -0,0 +1,60 @@
FreeModbus Coldfire MC523x PORT with lwIP
REQUIREMENTS
============
The FreeModbus/lwIP port requires are port of the lwIP TCP/IP stack for
the target platform. This port includes a suitable Ethernet driver for
lwIP as well as a FreeRTOS port.
The FreeModbus part itself does NOT depend on FreeRTOS or the Coldfire
ethernet controller and can therefore be used for creating other ports.
The development environment used is based on the GNU C Compiler for
a m68k-elf target as well as the insight debugger with some patches for
the BDM interface[1]. GDB startup and linker scripts are supplied with
the demo for the M5235BCC evaluation kit from Freescale.
[1] ... BDM tools: http://sourceforge.net/projects/bdm/
USAGE
=====
A makefile is supplied with the demo application and a binary can be
produced by calling 'make all'. A special target 'debug' is provided
which executes the insight debugger. At the insight debugger prompt
one should select the appropriate target interface (either BDM/Direct
or BDM/TCP) and should download the application to the development
board. It is important that the GDB script setup-and-load is executed
prior to downloading to initialize the SDRAM. After downloading one
should call the GDB function 'execute' and the PC is set to the start
of the executable. Execution can be started by typing 'continue' at
the Insight console interface.
In addition it is possible to download the software to the flash. This can
be done by calling 'make flash-erase' and 'make flash-programm'.
By default the port using the following settings:
IP Address : 10.0.10.2
Netmask : 255.255.255.0
Gateway : 10.0.10.1
Modbus TCP Port : 502
COMMON PROBLEMS
===============
Most of the problems have their origin in the startup scripts. The
following list should serve as a checklist where each point must be
satisfied for the port to work.
- The FreeRTOS port only works correctly in the supervisor mode. There-
fore the Coldfire CPU must run in the supervisor mode.
- portVECTOR_TABLE does not point to the currently active vector table.
Please also note that the vector table must be in RAM such that the
FreeRTOS port can install a traphandler for the portYIELD() call.
$Id: README.txt,v 1.1 2006/08/30 23:18:06 wolti Exp $
MCF5235 + lwIP port - Copyright (c) 2006 Christian Walter.

View File

@@ -0,0 +1,205 @@
/* ------------------------ System includes ------------------------------- */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
/* ------------------------ FreeRTOS includes ----------------------------- */
#include "FreeRTOS.h"
#include "task.h"
/* ------------------------ LWIP includes --------------------------------- */
#include "lwip/api.h"
#include "lwip/tcpip.h"
#include "lwip/memp.h"
/* ------------------------ FreeModbus includes --------------------------- */
#include "mb.h"
/* ------------------------ Project includes ------------------------------ */
#include "mcf5xxx.h"
#include "mcf523x.h"
#include "netif/fec.h"
#include "serial.h"
/* ------------------------ Defines --------------------------------------- */
#define mainCOM_TEST_BAUD_RATE ( ( unsigned portLONG ) 38400 )
#define mainMB_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )
#define PROG "FreeModbus"
#define REG_INPUT_START 1000
#define REG_INPUT_NREGS 4
#define REG_HOLDING_START 2000
#define REG_HOLDING_NREGS 130
/* ----------------------- Static variables ---------------------------------*/
static USHORT usRegInputStart = REG_INPUT_START;
static USHORT usRegInputBuf[REG_INPUT_NREGS];
static USHORT usRegHoldingStart = REG_HOLDING_START;
static USHORT usRegHoldingBuf[REG_HOLDING_NREGS];
xComPortHandle xSTDComPort = NULL;
/* ------------------------ Static functions ------------------------------ */
static void vlwIPInit( void );
static void vMBServerTask( void *arg );
/* ------------------------ Implementation -------------------------------- */
int
main( int argc, char *argv[] )
{
asm volatile ( "move.w #0x2000, %sr\n\t" );
/* Initialize serial communication device. */
xSTDComPort = xSerialPortInitMinimal( 38400, 8 );
/* Initialize lwIP protocol stack. */
vlwIPInit( );
if( sys_thread_new( vMBServerTask, NULL, mainMB_TASK_PRIORITY ) == NULL )
{
fprintf( stderr, "%s: can't create modbus task!\r\n", PROG );
}
else
{
/* Now all the tasks have been started - start the scheduler. */
vTaskStartScheduler( );
}
/* Should never get here! */
return 0;
}
void
vlwIPInit( void )
{
/* Initialize lwIP and its interface layer. */
sys_init( );
mem_init( );
memp_init( );
pbuf_init( );
netif_init( );
ip_init( );
tcpip_init( NULL, NULL );
}
void
vMBServerTask( void *arg )
{
eMBErrorCode xStatus;
struct ip_addr xIpAddr, xNetMast, xGateway;
struct netif xFEC523x;
IP4_ADDR( &xIpAddr, 10, 0, 10, 2 );
IP4_ADDR( &xNetMast, 255, 255, 255, 0 );
IP4_ADDR( &xGateway, 10, 0, 10, 1 );
netif_add( &xFEC523x, &xIpAddr, &xNetMast, &xGateway, NULL, mcf523xfec_init, tcpip_input );
/* Make it the default interface */
netif_set_default( &xFEC523x );
/* Bring it up */
netif_set_up( &xFEC523x );
for( ;; )
{
if( eMBTCPInit( MB_TCP_PORT_USE_DEFAULT ) != MB_ENOERR )
{
fprintf( stderr, "%s: can't initialize modbus stack!\r\n", PROG );
}
else if( eMBEnable( ) != MB_ENOERR )
{
fprintf( stderr, "%s: can't enable modbus stack!\r\n", PROG );
}
else
{
do
{
xStatus = eMBPoll( );
}
while( xStatus == MB_ENOERR );
}
/* An error occured. Maybe we can restart. */
( void )eMBDisable( );
( void )eMBClose( );
}
}
eMBErrorCode
eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{
eMBErrorCode eStatus = MB_ENOERR;
int iRegIndex;
if( ( usAddress >= REG_INPUT_START )
&& ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
{
iRegIndex = ( int )( usAddress - usRegInputStart );
while( usNRegs > 0 )
{
*pucRegBuffer++ = ( unsigned char )( usRegInputBuf[iRegIndex] >> 8 );
*pucRegBuffer++ = ( unsigned char )( usRegInputBuf[iRegIndex] & 0xFF );
iRegIndex++;
usNRegs--;
}
}
else
{
eStatus = MB_ENOREG;
}
return eStatus;
}
eMBErrorCode
eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
{
eMBErrorCode eStatus = MB_ENOERR;
int iRegIndex;
if( ( usAddress >= REG_HOLDING_START ) &&
( usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS ) )
{
iRegIndex = ( int )( usAddress - usRegHoldingStart );
switch ( eMode )
{
/* Pass current register values to the protocol stack. */
case MB_REG_READ:
while( usNRegs > 0 )
{
*pucRegBuffer++ = ( UCHAR ) ( usRegHoldingBuf[iRegIndex] >> 8 );
*pucRegBuffer++ = ( UCHAR ) ( usRegHoldingBuf[iRegIndex] & 0xFF );
iRegIndex++;
usNRegs--;
}
break;
/* Update current register values with new values from the
* protocol stack. */
case MB_REG_WRITE:
while( usNRegs > 0 )
{
usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
iRegIndex++;
usNRegs--;
}
}
}
else
{
eStatus = MB_ENOREG;
}
return eStatus;
}
eMBErrorCode
eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
{
return MB_ENOREG;
}
eMBErrorCode
eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
{
return MB_ENOREG;
}

View File

@@ -0,0 +1,329 @@
<!DOCTYPE Project SYSTEM "http://www.slickedit.com/dtd/vse/10.0/vpj.dtd">
<Project
Version="10.0"
VendorName="SlickEdit"
WorkingDir="."
VCSProject="CVS:">
<Config
Name="Release"
OutputFile=""
CompilerConfigName="Latest Version">
<Menu>
<Target
Name="Compile"
MenuCaption="&amp;Compile"
CaptureOutputWith="ProcessBuffer"
SaveOption="SaveCurrent"
RunFromDir="%rw">
<Exec/>
</Target>
<Target
Name="Build"
MenuCaption="&amp;Build"
CaptureOutputWith="ProcessBuffer"
SaveOption="SaveWorkspaceFiles"
RunFromDir="%rw">
<Exec/>
</Target>
<Target
Name="Rebuild"
MenuCaption="&amp;Rebuild"
CaptureOutputWith="ProcessBuffer"
SaveOption="SaveWorkspaceFiles"
RunFromDir="%rw">
<Exec/>
</Target>
<Target
Name="Debug"
MenuCaption="&amp;Debug"
SaveOption="SaveNone"
RunFromDir="%rw">
<Exec/>
</Target>
<Target
Name="Execute"
MenuCaption="E&amp;xecute"
SaveOption="SaveNone"
RunFromDir="%rw">
<Exec CmdLine='"demo.exe"'/>
</Target>
</Menu>
</Config>
<CustomFolders>
<Folder
Name="Source Files"
Filters="*.c;*.C;*.cc;*.cpp;*.cp;*.cxx;*.prg;*.pas;*.dpr;*.asm;*.s;*.bas;*.java;*.cs;*.sc;*.e;*.cob;*.html;*.rc;*.tcl;*.py;*.pl"/>
<Folder
Name="Header Files"
Filters="*.h;*.H;*.hh;*.hpp;*.hxx;*.inc;*.sh;*.cpy;*.if"/>
<Folder
Name="Resource Files"
Filters="*.ico;*.cur;*.dlg"/>
<Folder
Name="Bitmaps"
Filters="*.bmp"/>
<Folder
Name="Other Files"
Filters=""/>
</CustomFolders>
<Files AutoFolders="DirectoryView">
<Folder Name="freertos">
<Folder Name="include">
<F N="freertos/include/croutine.h"/>
<F N="freertos/include/FreeRTOS.h"/>
<F N="freertos/include/list.h"/>
<F N="freertos/include/portable.h"/>
<F N="freertos/include/projdefs.h"/>
<F N="freertos/include/queue.h"/>
<F N="freertos/include/semphr.h"/>
<F N="freertos/include/serial.h"/>
<F N="freertos/include/task.h"/>
</Folder>
<Folder Name="portable">
<Folder Name="GCC">
<Folder Name="MCF5235">
<F N="freertos/portable/GCC/MCF5235/port.c"/>
<F N="freertos/portable/GCC/MCF5235/portmacro.h"/>
</Folder>
</Folder>
<Folder Name="MemMang">
<F N="freertos/portable/MemMang/heap_1.c"/>
<F N="freertos/portable/MemMang/heap_2.c"/>
<F N="freertos/portable/MemMang/heap_3.c"/>
</Folder>
</Folder>
<F N="freertos/croutine.c"/>
<F N="freertos/list.c"/>
<F N="freertos/queue.c"/>
<F N="freertos/tasks.c"/>
</Folder>
<Folder Name="include">
<Folder Name="arch">
<Folder Name="mcf523x">
<F N="include/arch/mcf523x/mcf523x_can.h"/>
<F N="include/arch/mcf523x/mcf523x_ccm.h"/>
<F N="include/arch/mcf523x/mcf523x_cs.h"/>
<F N="include/arch/mcf523x/mcf523x_eport.h"/>
<F N="include/arch/mcf523x/mcf523x_etpu.h"/>
<F N="include/arch/mcf523x/mcf523x_fec.h"/>
<F N="include/arch/mcf523x/mcf523x_fmpll.h"/>
<F N="include/arch/mcf523x/mcf523x_gpio.h"/>
<F N="include/arch/mcf523x/mcf523x_i2c.h"/>
<F N="include/arch/mcf523x/mcf523x_intc0.h"/>
<F N="include/arch/mcf523x/mcf523x_intc1.h"/>
<F N="include/arch/mcf523x/mcf523x_mdha.h"/>
<F N="include/arch/mcf523x/mcf523x_pit.h"/>
<F N="include/arch/mcf523x/mcf523x_qspi.h"/>
<F N="include/arch/mcf523x/mcf523x_rcm.h"/>
<F N="include/arch/mcf523x/mcf523x_rng.h"/>
<F N="include/arch/mcf523x/mcf523x_scm.h"/>
<F N="include/arch/mcf523x/mcf523x_sdramc.h"/>
<F N="include/arch/mcf523x/mcf523x_skha.h"/>
<F N="include/arch/mcf523x/mcf523x_sram.h"/>
<F N="include/arch/mcf523x/mcf523x_timer.h"/>
<F N="include/arch/mcf523x/mcf523x_uart.h"/>
<F N="include/arch/mcf523x/mcf523x_wtm.h"/>
</Folder>
<F N="include/arch/mcf523x.h"/>
<F N="include/arch/mcf5xxx.h"/>
</Folder>
</Folder>
<Folder Name="lwip">
<Folder Name="contrib">
<Folder Name="port">
<Folder Name="FreeRTOS">
<Folder Name="MCF5235">
<Folder Name="arch">
<F N="lwip/contrib/port/FreeRTOS/MCF5235/arch/cc.h"/>
<F N="lwip/contrib/port/FreeRTOS/MCF5235/arch/cpu.h"/>
<F N="lwip/contrib/port/FreeRTOS/MCF5235/arch/lib.h"/>
<F N="lwip/contrib/port/FreeRTOS/MCF5235/arch/perf.h"/>
<F N="lwip/contrib/port/FreeRTOS/MCF5235/arch/sys_arch.h"/>
</Folder>
<Folder Name="netif">
<F N="lwip/contrib/port/FreeRTOS/MCF5235/netif/fec.c"/>
<F N="lwip/contrib/port/FreeRTOS/MCF5235/netif/fec.h"/>
<F N="lwip/contrib/port/FreeRTOS/MCF5235/netif/nbuf.c"/>
<F N="lwip/contrib/port/FreeRTOS/MCF5235/netif/nbuf.h"/>
</Folder>
<F N="lwip/contrib/port/FreeRTOS/MCF5235/sys_arch.c"/>
</Folder>
</Folder>
</Folder>
</Folder>
<Folder Name="src">
<Folder Name="api">
<F N="lwip/src/api/api_lib.c"/>
<F N="lwip/src/api/api_msg.c"/>
<F N="lwip/src/api/err.c"/>
<F N="lwip/src/api/sockets.c"/>
<F N="lwip/src/api/tcpip.c"/>
</Folder>
<Folder Name="core">
<Folder Name="ipv4">
<F N="lwip/src/core/ipv4/icmp.c"/>
<F N="lwip/src/core/ipv4/ip.c"/>
<F N="lwip/src/core/ipv4/ip_addr.c"/>
<F N="lwip/src/core/ipv4/ip_frag.c"/>
</Folder>
<Folder Name="ipv6">
<F N="lwip/src/core/ipv6/icmp6.c"/>
<F N="lwip/src/core/ipv6/ip6.c"/>
<F N="lwip/src/core/ipv6/ip6_addr.c"/>
</Folder>
<F N="lwip/src/core/dhcp.c"/>
<F N="lwip/src/core/inet.c"/>
<F N="lwip/src/core/inet6.c"/>
<F N="lwip/src/core/mem.c"/>
<F N="lwip/src/core/memp.c"/>
<F N="lwip/src/core/netif.c"/>
<F N="lwip/src/core/pbuf.c"/>
<F N="lwip/src/core/raw.c"/>
<F N="lwip/src/core/stats.c"/>
<F N="lwip/src/core/sys.c"/>
<F N="lwip/src/core/tcp.c"/>
<F N="lwip/src/core/tcp_in.c"/>
<F N="lwip/src/core/tcp_out.c"/>
<F N="lwip/src/core/udp.c"/>
</Folder>
<Folder Name="include">
<Folder Name="ipv4">
<Folder Name="lwip">
<F N="lwip/src/include/ipv4/lwip/icmp.h"/>
<F N="lwip/src/include/ipv4/lwip/inet.h"/>
<F N="lwip/src/include/ipv4/lwip/ip.h"/>
<F N="lwip/src/include/ipv4/lwip/ip_addr.h"/>
<F N="lwip/src/include/ipv4/lwip/ip_frag.h"/>
</Folder>
</Folder>
<Folder Name="ipv6">
<Folder Name="lwip">
<F N="lwip/src/include/ipv6/lwip/icmp.h"/>
<F N="lwip/src/include/ipv6/lwip/inet.h"/>
<F N="lwip/src/include/ipv6/lwip/ip.h"/>
<F N="lwip/src/include/ipv6/lwip/ip_addr.h"/>
</Folder>
</Folder>
<Folder Name="lwip">
<F N="lwip/src/include/lwip/api.h"/>
<F N="lwip/src/include/lwip/api_msg.h"/>
<F N="lwip/src/include/lwip/arch.h"/>
<F N="lwip/src/include/lwip/debug.h"/>
<F N="lwip/src/include/lwip/def.h"/>
<F N="lwip/src/include/lwip/dhcp.h"/>
<F N="lwip/src/include/lwip/err.h"/>
<F N="lwip/src/include/lwip/mem.h"/>
<F N="lwip/src/include/lwip/memp.h"/>
<F N="lwip/src/include/lwip/netif.h"/>
<F N="lwip/src/include/lwip/opt.h"/>
<F N="lwip/src/include/lwip/pbuf.h"/>
<F N="lwip/src/include/lwip/raw.h"/>
<F N="lwip/src/include/lwip/sio.h"/>
<F N="lwip/src/include/lwip/snmp.h"/>
<F N="lwip/src/include/lwip/sockets.h"/>
<F N="lwip/src/include/lwip/stats.h"/>
<F N="lwip/src/include/lwip/sys.h"/>
<F N="lwip/src/include/lwip/tcp.h"/>
<F N="lwip/src/include/lwip/tcpip.h"/>
<F N="lwip/src/include/lwip/udp.h"/>
</Folder>
<Folder Name="netif">
<F N="lwip/src/include/netif/etharp.h"/>
<F N="lwip/src/include/netif/loopif.h"/>
<F N="lwip/src/include/netif/slipif.h"/>
</Folder>
</Folder>
<Folder Name="netif">
<Folder Name="ppp">
<F N="lwip/src/netif/ppp/auth.c"/>
<F N="lwip/src/netif/ppp/auth.h"/>
<F N="lwip/src/netif/ppp/chap.c"/>
<F N="lwip/src/netif/ppp/chap.h"/>
<F N="lwip/src/netif/ppp/chpms.c"/>
<F N="lwip/src/netif/ppp/chpms.h"/>
<F N="lwip/src/netif/ppp/fsm.c"/>
<F N="lwip/src/netif/ppp/fsm.h"/>
<F N="lwip/src/netif/ppp/ipcp.c"/>
<F N="lwip/src/netif/ppp/ipcp.h"/>
<F N="lwip/src/netif/ppp/lcp.c"/>
<F N="lwip/src/netif/ppp/lcp.h"/>
<F N="lwip/src/netif/ppp/magic.c"/>
<F N="lwip/src/netif/ppp/magic.h"/>
<F N="lwip/src/netif/ppp/md5.c"/>
<F N="lwip/src/netif/ppp/md5.h"/>
<F N="lwip/src/netif/ppp/pap.c"/>
<F N="lwip/src/netif/ppp/pap.h"/>
<F N="lwip/src/netif/ppp/ppp.c"/>
<F N="lwip/src/netif/ppp/ppp.h"/>
<F N="lwip/src/netif/ppp/pppdebug.h"/>
<F N="lwip/src/netif/ppp/randm.c"/>
<F N="lwip/src/netif/ppp/randm.h"/>
<F N="lwip/src/netif/ppp/vj.c"/>
<F N="lwip/src/netif/ppp/vj.h"/>
<F N="lwip/src/netif/ppp/vjbsdhdr.h"/>
</Folder>
<F N="lwip/src/netif/etharp.c"/>
<F N="lwip/src/netif/ethernetif.c"/>
<F N="lwip/src/netif/loopif.c"/>
<F N="lwip/src/netif/slipif.c"/>
</Folder>
</Folder>
</Folder>
<Folder Name="../../modbus">
<Folder Name="ascii">
<F N="../../modbus/ascii/mbascii.c"/>
<F N="../../modbus/ascii/mbascii.h"/>
</Folder>
<Folder Name="functions">
<F N="../../modbus/functions/mbfunccoils.c"/>
<F N="../../modbus/functions/mbfuncdiag.c"/>
<F N="../../modbus/functions/mbfuncdisc.c"/>
<F N="../../modbus/functions/mbfuncholding.c"/>
<F N="../../modbus/functions/mbfuncinput.c"/>
<F N="../../modbus/functions/mbfuncother.c"/>
<F N="../../modbus/functions/mbutils.c"/>
</Folder>
<Folder Name="include">
<F N="../../modbus/include/mb.h"/>
<F N="../../modbus/include/mbconfig.h"/>
<F N="../../modbus/include/mbframe.h"/>
<F N="../../modbus/include/mbfunc.h"/>
<F N="../../modbus/include/mbport.h"/>
<F N="../../modbus/include/mbproto.h"/>
<F N="../../modbus/include/mbutils.h"/>
</Folder>
<Folder Name="rtu">
<F N="../../modbus/rtu/mbcrc.c"/>
<F N="../../modbus/rtu/mbcrc.h"/>
<F N="../../modbus/rtu/mbrtu.c"/>
<F N="../../modbus/rtu/mbrtu.h"/>
</Folder>
<Folder Name="tcp">
<F N="../../modbus/tcp/mbtcp.c"/>
<F N="../../modbus/tcp/mbtcp.h"/>
</Folder>
<F N="../../modbus/mb.c"/>
</Folder>
<Folder Name="port">
<F N="port/mbconfig.h"/>
<F N="port/port.h"/>
<F N="port/portevent.c"/>
<F N="port/portother.c"/>
<F N="port/porttcp.c"/>
</Folder>
<Folder Name="system">
<F N="system/crt0.S"/>
<F N="system/init.c"/>
<F N="system/mcf5xxx.S"/>
<F N="system/newlib.c"/>
<F N="system/serial.c"/>
<F N="system/vector.S"/>
</Folder>
<Folder Name="../../tools">
<F N="../../tools/modpoll.cpp"/>
</Folder>
<F N="demo.c"/>
<F N="FreeRTOSConfig.h"/>
<F N="lwipopts.h"/>
</Files>
</Project>

View File

@@ -0,0 +1,342 @@
/*
FreeRTOS.org V4.0.5 - Copyright (C) 2003-2006 Richard Barry.
This file is part of the FreeRTOS.org distribution.
FreeRTOS.org is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FreeRTOS.org is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FreeRTOS.org; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS.org, without being obliged to provide
the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details of how and when the exception
can be applied.
***************************************************************************
See http://www.FreeRTOS.org for documentation, latest information, license
and contact details. Please ensure to read the configuration and relevant
port sections of the online documentation.
***************************************************************************
*/
#include "FreeRTOS.h"
#include "task.h"
#include "croutine.h"
/* Lists for ready and blocked co-routines. --------------------*/
static xList pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */
static xList xDelayedCoRoutineList1; /*< Delayed co-routines. */
static xList xDelayedCoRoutineList2; /*< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */
static xList * pxDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used. */
static xList * pxOverflowDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */
static xList xPendingReadyList; /*< Holds co-routines that have been readied by an external event. They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */
/* Other file private variables. --------------------------------*/
corCRCB * pxCurrentCoRoutine = NULL;
static unsigned portBASE_TYPE uxTopCoRoutineReadyPriority = 0;
static portTickType xCoRoutineTickCount = 0;
/* The initial state of the co-routine when it is created. */
#define corINITIAL_STATE ( 0 )
/*
* Place the co-routine represented by pxCRCB into the appropriate ready queue
* for the priority. It is inserted at the end of the list.
*
* This macro accesses the co-routine ready lists and therefore must not be
* used from within an ISR.
*/
#define prvAddCoRoutineToReadyQueue( pxCRCB ) \
{ \
if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority ) \
{ \
uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \
} \
vListInsertEnd( ( xList * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \
}
/*
* Utility to ready all the lists used by the scheduler. This is called
* automatically upon the creation of the first co-routine.
*/
static void prvInitialiseCoRoutineLists( void );
/*
* Co-routines that are readied by an interrupt cannot be placed directly into
* the ready lists (there is no mutual exclusion). Instead they are placed in
* in the pending ready list in order that they can later be moved to the ready
* list by the co-routine scheduler.
*/
static inline void prvCheckPendingReadyList( void );
/*
* Macro that looks at the list of co-routines that are currently delayed to
* see if any require waking.
*
* Co-routines are stored in the queue in the order of their wake time -
* meaning once one co-routine has been found whose timer has not expired
* we need not look any further down the list.
*/
static inline void prvCheckDelayedList( void );
/*-----------------------------------------------------------*/
portBASE_TYPE xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, unsigned portBASE_TYPE uxPriority, unsigned portBASE_TYPE uxIndex )
{
portBASE_TYPE xReturn;
corCRCB *pxCoRoutine;
/* Allocate the memory that will store the co-routine control block. */
pxCoRoutine = ( corCRCB * ) pvPortMalloc( sizeof( corCRCB ) );
if( pxCoRoutine )
{
/* If pxCurrentCoRoutine is NULL then this is the first co-routine to
be created and the co-routine data structures need initialising. */
if( pxCurrentCoRoutine == NULL )
{
pxCurrentCoRoutine = pxCoRoutine;
prvInitialiseCoRoutineLists();
}
/* Check the priority is within limits. */
if( uxPriority >= configMAX_CO_ROUTINE_PRIORITIES )
{
uxPriority = configMAX_CO_ROUTINE_PRIORITIES - 1;
}
/* Fill out the co-routine control block from the function parameters. */
pxCoRoutine->uxState = corINITIAL_STATE;
pxCoRoutine->uxPriority = uxPriority;
pxCoRoutine->uxIndex = uxIndex;
pxCoRoutine->pxCoRoutineFunction = pxCoRoutineCode;
/* Initialise all the other co-routine control block parameters. */
vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) );
vListInitialiseItem( &( pxCoRoutine->xEventListItem ) );
/* Set the co-routine control block as a link back from the xListItem.
This is so we can get back to the containing CRCB from a generic item
in a list. */
listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine );
listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine );
/* Event lists are always in priority order. */
listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) uxPriority );
/* Now the co-routine has been initialised it can be added to the ready
list at the correct priority. */
prvAddCoRoutineToReadyQueue( pxCoRoutine );
xReturn = pdPASS;
}
else
{
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
}
return xReturn;
}
/*-----------------------------------------------------------*/
void vCoRoutineAddToDelayedList( portTickType xTicksToDelay, xList *pxEventList )
{
portTickType xTimeToWake;
/* Calculate the time to wake - this may overflow but this is
not a problem. */
xTimeToWake = xCoRoutineTickCount + xTicksToDelay;
/* We must remove ourselves from the ready list before adding
ourselves to the blocked list as the same list item is used for
both lists. */
vListRemove( ( xListItem * ) &( pxCurrentCoRoutine->xGenericListItem ) );
/* The list item will be inserted in wake time order. */
listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake );
if( xTimeToWake < xCoRoutineTickCount )
{
/* Wake time has overflowed. Place this item in the
overflow list. */

View File

@@ -0,0 +1,111 @@
/*
FreeRTOS.org V4.0.5 - Copyright (C) 2003-2006 Richard Barry.
This file is part of the FreeRTOS.org distribution.
FreeRTOS.org is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FreeRTOS.org is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FreeRTOS.org; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS.org, without being obliged to provide
the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details of how and when the exception
can be applied.
***************************************************************************
See http://www.FreeRTOS.org for documentation, latest information, license
and contact details. Please ensure to read the configuration and relevant
port sections of the online documentation.
***************************************************************************
*/
#ifndef INC_FREERTOS_H
#define INC_FREERTOS_H
/*
* Include the generic headers required for the FreeRTOS port being used.
*/
#include <stddef.h>
/* Basic FreeRTOS definitions. */
#include "projdefs.h"
/* Application specific configuration options. */
#include "FreeRTOSConfig.h"
/* Definitions specific to the port being used. */
#include "portable.h"

View File

@@ -0,0 +1,713 @@
/*
FreeRTOS.org V4.0.5 - Copyright (C) 2003-2006 Richard Barry.
This file is part of the FreeRTOS.org distribution.
FreeRTOS.org is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FreeRTOS.org is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FreeRTOS.org; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS.org, without being obliged to provide
the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details of how and when the exception
can be applied.
***************************************************************************
See http://www.FreeRTOS.org for documentation, latest information, license
and contact details. Please ensure to read the configuration and relevant
port sections of the online documentation.
***************************************************************************
*/
#ifndef CO_ROUTINE_H
#define CO_ROUTINE_H
#include "list.h"
/* Used to hide the implementation of the co-routine control block. The
control block structure however has to be included in the header due to
the macro implementation of the co-routine functionality. */
typedef void * xCoRoutineHandle;
/* Defines the prototype to which co-routine functions must conform. */
typedef void (*crCOROUTINE_CODE)( xCoRoutineHandle, unsigned portBASE_TYPE );
typedef struct corCoRoutineControlBlock
{
crCOROUTINE_CODE pxCoRoutineFunction;
xListItem xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */
xListItem xEventListItem; /*< List item used to place the CRCB in event lists. */
unsigned portBASE_TYPE uxPriority; /*< The priority of the co-routine in relation to other co-routines. */
unsigned portBASE_TYPE uxIndex; /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */
unsigned portSHORT uxState; /*< Used internally by the co-routine implementation. */
} corCRCB; /* Co-routine control block. Note must be identical in size down to uxPriority with tskTCB. */
/**
* croutine. h
*<pre>
portBASE_TYPE xCoRoutineCreate(
crCOROUTINE_CODE pxCoRoutineCode,
unsigned portBASE_TYPE uxPriority,
unsigned portBASE_TYPE uxIndex
);</pre>
*
* Create a new co-routine and add it to the list of co-routines that are
* ready to run.
*
* @param pxCoRoutineCode Pointer to the co-routine function. Co-routine
* functions require special syntax - see the co-routine section of the WEB
* documentation for more information.
*
* @param uxPriority The priority with respect to other co-routines at which
* the co-routine will run.
*
* @param uxIndex Used to distinguish between different co-routines that
* execute the same function. See the example below and the co-routine section
* of the WEB documentation for further information.
*
* @return pdPASS if the co-routine was successfully created and added to a ready
* list, otherwise an error code defined with ProjDefs.h.
*
* Example usage:
<pre>
// Co-routine to be created.
void vFlashCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
{
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
// This may not be necessary for const variables.
static const char cLedToFlash[ 2 ] = { 5, 6 };
static const portTickType xTimeToDelay[ 2 ] = { 200, 400 };
// Must start every co-routine with a call to crSTART();
crSTART( xHandle );
for( ;; )
{
// This co-routine just delays for a fixed period, then toggles
// an LED. Two co-routines are created using this function, so
// the uxIndex parameter is used to tell the co-routine which
// LED to flash and how long to delay. This assumes xQueue has
// already been created.
vParTestToggleLED( cLedToFlash[ uxIndex ] );
crDELAY( xHandle, uxFlashRates[ uxIndex ] );
}
// Must end every co-routine with a call to crEND();
crEND();
}
// Function that creates two co-routines.
void vOtherFunction( void )
{
unsigned char ucParameterToPass;
xTaskHandle xHandle;
// Create two co-routines at priority 0. The first is given index 0
// so (from the code above) toggles LED 5 every 200 ticks. The second
// is given index 1 so toggles LED 6 every 400 ticks.
for( uxIndex = 0; uxIndex < 2; uxIndex++ )
{
xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
}
}
</pre>
* \defgroup xCoRoutineCreate xCoRoutineCreate
* \ingroup Tasks
*/
portBASE_TYPE xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, unsigned portBASE_TYPE uxPriority, unsigned portBASE_TYPE uxIndex );
/**
* croutine. h
*<pre>
void vCoRoutineSchedule( void );</pre>
*
* Run a co-routine.
*
* vCoRoutineSchedule() executes the highest priority co-routine that is able
* to run. The co-routine will execute until it either blocks, yields or is
* preempted by a task. Co-routines execute cooperatively so one
* co-routine cannot be preempted by another, but can be preempted by a task.
*
* If an application comprises of both tasks and co-routines then
* vCoRoutineSchedule should be called from the idle task (in an idle task
* hook).
*
* Example usage:
<pre>
// This idle task hook will schedule a co-routine each time it is called.
// The rest of the idle task will execute between co-routine calls.
void vApplicationIdleHook( void )
{
vCoRoutineSchedule();
}
// Alternatively, if you do not require any other part of the idle task to
// execute, the idle task hook can call vCoRoutineScheduler() within an
// infinite loop.
void vApplicationIdleHook( void )
{
for( ;; )
{
vCoRoutineSchedule();
}
}
</pre>
* \defgroup vCoRoutineSchedule vCoRoutineSchedule
* \ingroup Tasks
*/
void vCoRoutineSchedule( void );
/**
* croutine. h
* <pre>
crSTART( xCoRoutineHandle xHandle );</pre>
*
* This macro MUST always be called at the start of a co-routine function.
*
* Example usage:
<pre>
// Co-routine to be created.
void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
{
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
static portLONG ulAVariable;
// Must start every co-routine with a call to crSTART();
crSTART( xHandle );
for( ;; )
{
// Co-routine functionality goes here.
}
// Must end every co-routine with a call to crEND();
crEND();
}</pre>
* \defgroup crSTART crSTART
* \ingroup Tasks
*/
#define crSTART( pxCRCB ) switch( ( ( corCRCB * )pxCRCB )->uxState ) { case 0:
/**
* croutine. h
* <pre>
crEND();</pre>
*
* This macro MUST always be called at the end of a co-routine function.
*
* Example usage:
<pre>
// Co-routine to be created.
void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
{
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
static portLONG ulAVariable;
// Must start every co-routine with a call to crSTART();
crSTART( xHandle );
for( ;; )
{
// Co-routine functionality goes here.
}
// Must end every co-routine with a call to crEND();
crEND();
}</pre>
* \defgroup crSTART crSTART
* \ingroup Tasks
*/
#define crEND() }
/*
* These macros are intended for internal use by the co-routine implementation
* only. The macros should not be used directly by application writers.
*/
#define crSET_STATE0( xHandle ) ( ( corCRCB * )xHandle)->uxState = (__LINE__ * 2); return; case (__LINE__ * 2):
#define crSET_STATE1( xHandle ) ( ( corCRCB * )xHandle)->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1):
/**
* croutine. h
*<pre>
crDELAY( xCoRoutineHandle xHandle, portTickType xTicksToDelay );</pre>
*
* Delay a co-routine for a fixed period of time.
*
* crDELAY can only be called from the co-routine function itself - not
* from within a function called by the co-routine function. This is because
* co-routines do not maintain their own stack.
*
* @param xHandle The handle of the co-routine to delay. This is the xHandle
* parameter of the co-routine function.
*
* @param xTickToDelay The number of ticks that the co-routine should delay
* for. The actual amount of time this equates to is defined by
* configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_RATE_MS
* can be used to convert ticks to milliseconds.
*
* Example usage:
<pre>
// Co-routine to be created.
void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
{
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
// This may not be necessary for const variables.
// We are to delay for 200ms.
static const xTickType xDelayTime = 200 / portTICK_RATE_MS;
// Must start every co-routine with a call to crSTART();
crSTART( xHandle );
for( ;; )
{
// Delay for 200ms.
crDELAY( xHandle, xDelayTime );
// Do something here.
}
// Must end every co-routine with a call to crEND();
crEND();
}</pre>
* \defgroup crDELAY crDELAY
* \ingroup Tasks
*/
#define crDELAY( xHandle, xTicksToDelay ) \
if( xTicksToDelay > 0 ) \
{ \
vCoRoutineAddToDelayedList( xTicksToDelay, NULL ); \
} \
crSET_STATE0( xHandle );
/**
* <pre>
crQUEUE_SEND(
xCoRoutineHandle xHandle,
xQueueHandle pxQueue,
void *pvItemToQueue,
portTickType xTicksToWait,
portBASE_TYPE *pxResult
)</pre>
*
* The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
* equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
*
* crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
* xQueueSend() and xQueueReceive() can only be used from tasks.
*
* crQUEUE_SEND can only be called from the co-routine function itself - not
* from within a function called by the co-routine function. This is because
* co-routines do not maintain their own stack.
*
* See the co-routine section of the WEB documentation for information on
* passing data between tasks and co-routines and between ISR's and
* co-routines.
*
* @param xHandle The handle of the calling co-routine. This is the xHandle
* parameter of the co-routine function.
*
* @param pxQueue The handle of the queue on which the data will be posted.
* The handle is obtained as the return value when the queue is created using
* the xQueueCreate() API function.
*
* @param pvItemToQueue A pointer to the data being posted onto the queue.
* The number of bytes of each queued item is specified when the queue is
* created. This number of bytes is copied from pvItemToQueue into the queue
* itself.
*
* @param xTickToDelay The number of ticks that the co-routine should block
* to wait for space to become available on the queue, should space not be
* available immediately. The actual amount of time this equates to is defined
* by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant
* portTICK_RATE_MS can be used to convert ticks to milliseconds (see example
* below).
*
* @param pxResult The variable pointed to by pxResult will be set to pdPASS if
* data was successfully posted onto the queue, otherwise it will be set to an
* error defined within ProjDefs.h.
*
* Example usage:
<pre>
// Co-routine function that blocks for a fixed period then posts a number onto
// a queue.
static void prvCoRoutineFlashTask( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
{
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
static portBASE_TYPE xNumberToPost = 0;
static portBASE_TYPE xResult;
// Co-routines must begin with a call to crSTART().
crSTART( xHandle );
for( ;; )
{
// This assumes the queue has already been created.
crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );

View File

@@ -0,0 +1,270 @@
/*
FreeRTOS.org V4.0.5 - Copyright (C) 2003-2006 Richard Barry.
This file is part of the FreeRTOS.org distribution.
FreeRTOS.org is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FreeRTOS.org is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FreeRTOS.org; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS.org, without being obliged to provide
the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details of how and when the exception
can be applied.
***************************************************************************
See http://www.FreeRTOS.org for documentation, latest information, license
and contact details. Please ensure to read the configuration and relevant
port sections of the online documentation.
***************************************************************************
*/
/*
* This is the list implementation used by the scheduler. While it is tailored
* heavily for the schedulers needs, it is also available for use by
* application code.
*
* xLists can only store pointers to xListItems. Each xListItem contains a
* numeric value (xItemValue). Most of the time the lists are sorted in
* descending item value order.
*
* Lists are created already containing one list item. The value of this
* item is the maximum possible that can be stored, it is therefore always at
* the end of the list and acts as a marker. The list member pxHead always
* points to this marker - even though it is at the tail of the list. This
* is because the tail contains a wrap back pointer to the true head of
* the list.
*
* In addition to it's value, each list item contains a pointer to the next
* item in the list (pxNext), a pointer to the list it is in (pxContainer)
* and a pointer to back to the object that contains it. These later two
* pointers are included for efficiency of list manipulation. There is
* effectively a two way link between the object containing the list item and
* the list item itself.
*
*
* \page ListIntroduction List Implementation
* \ingroup FreeRTOSIntro
*/
#ifndef LIST_H
#define LIST_H
/*
* Definition of the only type of object that a list can contain.
*/
struct xLIST_ITEM
{
portTickType xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */
volatile struct xLIST_ITEM * pxNext; /*< Pointer to the next xListItem in the list. */
volatile struct xLIST_ITEM * pxPrevious;/*< Pointer to the previous xListItem in the list. */
void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */
void * pvContainer; /*< Pointer to the list in which this list item is placed (if any). */
};
typedef struct xLIST_ITEM xListItem; /* For some reason lint wants this as two separate definitions. */
struct xMINI_LIST_ITEM
{
portTickType xItemValue;
volatile struct xLIST_ITEM *pxNext;
volatile struct xLIST_ITEM *pxPrevious;
};
typedef struct xMINI_LIST_ITEM xMiniListItem;
/*
* Definition of the type of queue used by the scheduler.
*/
typedef struct xLIST
{
volatile unsigned portBASE_TYPE uxNumberOfItems;
volatile xListItem * pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to pvListGetOwnerOfNextEntry (). */
volatile xMiniListItem xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */
} xList;
/*
* Access macro to set the owner of a list item. The owner of a list item
* is the object (usually a TCB) that contains the list item.
*
* \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
* \ingroup LinkedList
*/
#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( pxListItem )->pvOwner = ( void * ) pxOwner
/*
* Access macro to set the value of the list item. In most cases the value is
* used to sort the list in descending order.
*
* \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE
* \ingroup LinkedList
*/
#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( pxListItem )->xItemValue = xValue
/*
* Access macro the retrieve the value of the list item. The value can
* represent anything - for example a the priority of a task, or the time at
* which a task should be unblocked.
*
* \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
* \ingroup LinkedList
*/
#define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue )
/*
* Access macro to determine if a list contains any items. The macro will
* only have the value true if the list is empty.
*
* \page listLIST_IS_EMPTY listLIST_IS_EMPTY
* \ingroup LinkedList
*/
#define listLIST_IS_EMPTY( pxList ) ( ( pxList )->uxNumberOfItems == ( unsigned portBASE_TYPE ) 0 )
/*
* Access macro to return the number of items in the list.
*/

View File

@@ -0,0 +1,192 @@
/*
FreeRTOS.org V4.0.5 - Copyright (C) 2003-2006 Richard Barry.
This file is part of the FreeRTOS.org distribution.
FreeRTOS.org is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FreeRTOS.org is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FreeRTOS.org; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS.org, without being obliged to provide
the source code for any proprietary components. See the licensing section
of http:www.FreeRTOS.org for full details of how and when the exception
can be applied.
***************************************************************************
See http:www.FreeRTOS.org for documentation, latest information, license
and contact details. Please ensure to read the configuration and relevant
port sections of the online documentation.
***************************************************************************
*/
/*-----------------------------------------------------------
* Portable layer API. Each function must be defined for each port.
*----------------------------------------------------------*/
#ifndef PORTABLE_H
#define PORTABLE_H
/* Include the macro file relevant to the port being used. */
#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT
#include "..\..\source\portable\owatcom\16bitdos\pc\portmacro.h"
typedef void ( __interrupt __far *pxISR )();
#endif
#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT
#include "..\..\source\portable\owatcom\16bitdos\flsh186\portmacro.h"
typedef void ( __interrupt __far *pxISR )();
#endif
#ifdef GCC_MEGA_AVR
#include "../portable/GCC/ATMega323/portmacro.h"
#endif
#ifdef IAR_MEGA_AVR
#include "../portable/IAR/ATMega323/portmacro.h"
#endif
#ifdef MPLAB_PIC18F_PORT
#include "..\..\source\portable\MPLAB\PIC18F\portmacro.h"
#endif
#ifdef _FEDPICC
#include "libFreeRTOS/Include/portmacro.h"
#endif
#ifdef SDCC_CYGNAL
#include "../../Source/portable/SDCC/Cygnal/portmacro.h"
#endif
#ifdef GCC_ARM7
#include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h"
#endif
#ifdef GCC_MSP430
#include "../../Source/portable/GCC/MSP430F449/portmacro.h"
#endif
#ifdef ROWLEY_MSP430
#include "../../Source/portable/Rowley/MSP430F449/portmacro.h"
#endif
#ifdef KEIL_ARM7
#include "..\..\Source\portable\Keil\ARM7\portmacro.h"
#endif
#ifdef SAM7_GCC
#include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h"
#endif
#ifdef SAM7_IAR
#include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h"
#endif
#ifdef LPC2000_IAR

View File

@@ -0,0 +1,54 @@
/*
FreeRTOS.org V4.0.5 - Copyright (C) 2003-2006 Richard Barry.
This file is part of the FreeRTOS.org distribution.
FreeRTOS.org is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FreeRTOS.org is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FreeRTOS.org; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS.org, without being obliged to provide
the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details of how and when the exception
can be applied.
***************************************************************************
See http://www.FreeRTOS.org for documentation, latest information, license

View File

@@ -0,0 +1,471 @@
/*
FreeRTOS.org V4.0.5 - Copyright (C) 2003-2006 Richard Barry.
This file is part of the FreeRTOS.org distribution.
FreeRTOS.org is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FreeRTOS.org is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FreeRTOS.org; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS.org, without being obliged to provide
the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details of how and when the exception
can be applied.
***************************************************************************
See http://www.FreeRTOS.org for documentation, latest information, license
and contact details. Please ensure to read the configuration and relevant
port sections of the online documentation.
***************************************************************************
*/
#ifndef QUEUE_H
#define QUEUE_H
typedef void * xQueueHandle;
/**
* queue. h
* <pre>
xQueueHandle xQueueCreate(
unsigned portBASE_TYPE uxQueueLength,
unsigned portBASE_TYPE uxItemSize
);
* </pre>
*
* Creates a new queue instance. This allocates the storage required by the
* new queue and returns a handle for the queue.
*
* @param uxQueueLength The maximum number of items that the queue can contain.
*
* @param uxItemSize The number of bytes each item in the queue will require.
* Items are queued by copy, not by reference, so this is the number of bytes
* that will be copied for each posted item. Each item on the queue must be
* the same size.
*
* @return If the queue is successfully create then a handle to the newly
* created queue is returned. If the queue cannot be created then 0 is
* returned.
*
* Example usage:
<pre>
struct AMessage
{
portCHAR ucMessageID;
portCHAR ucData[ 20 ];
};
void vATask( void *pvParameters )
{
xQueueHandle xQueue1, xQueue2;
// Create a queue capable of containing 10 unsigned long values.
xQueue1 = xQueueCreate( 10, sizeof( unsigned portLONG ) );
if( xQueue1 == 0 )
{
// Queue was not created and must not be used.
}
// Create a queue capable of containing 10 pointers to AMessage structures.
// These should be passed by pointer as they contain a lot of data.
xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
if( xQueue2 == 0 )
{
// Queue was not created and must not be used.
}
// ... Rest of task code.
}
</pre>
* \defgroup xQueueCreate xQueueCreate
* \ingroup QueueManagement
*/
xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize );
/**
* queue. h
* <pre>
portBASE_TYPE xQueueSend(
xQueueHandle xQueue,
const void * pvItemToQueue,
portTickType xTicksToWait
);
* </pre>
*
* Post an item on a queue. The item is queued by copy, not by reference.
* This function must not be called from an interrupt service routine.
* See xQueueSendFromISR () for an alternative which may be used in an ISR.
*
* @param xQueue The handle to the queue on which the item is to be posted.
*
* @param pvItemToQueue A pointer to the item that is to be placed on the
* queue. The size of the items the queue will hold was defined when the
* queue was created, so this many bytes will be copied from pvItemToQueue
* into the queue storage area.
*
* @param xTicksToWait The maximum amount of time the task should block
* waiting for space to become available on the queue, should it already
* be full. The call will return immediately if this is set to 0. The
* time is defined in tick periods so the constant portTICK_RATE_MS
* should be used to convert to real time if this is required.
*
* @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.
*
* Example usage:
<pre>
struct AMessage
{
portCHAR ucMessageID;
portCHAR ucData[ 20 ];
} xMessage;
unsigned portLONG ulVar = 10UL;
void vATask( void *pvParameters )
{
xQueueHandle xQueue1, xQueue2;
struct AMessage *pxMessage;
// Create a queue capable of containing 10 unsigned long values.
xQueue1 = xQueueCreate( 10, sizeof( unsigned portLONG ) );
// Create a queue capable of containing 10 pointers to AMessage structures.
// These should be passed by pointer as they contain a lot of data.
xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
// ...
if( xQueue1 != 0 )
{
// Send an unsigned long. Wait for 10 ticks for space to become
// available if necessary.
if( xQueueSend( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS )
{
// Failed to post the message, even after 10 ticks.
}
}
if( xQueue2 != 0 )
{
// Send a pointer to a struct AMessage object. Don't block if the
// queue is already full.
pxMessage = & xMessage;
xQueueSend( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );
}
// ... Rest of task code.
}
</pre>
* \defgroup xQueueSend xQueueSend
* \ingroup QueueManagement
*/
signed portBASE_TYPE xQueueSend( xQueueHandle xQueue, const void * pvItemToQueue, portTickType xTicksToWait );
/**
* queue. h
* <pre>
portBASE_TYPE xQueueReceive(
xQueueHandle xQueue,
void *pvBuffer,
portTickType xTicksToWait
);</pre>
*
* Receive an item from a queue. The item is received by copy so a buffer of
* adequate size must be provided. The number of bytes copied into the buffer
* was defined when the queue was created.
*
* This function must not be used in an interrupt service routine. See
* xQueueReceiveFromISR for an alternative that can.
*
* @param pxQueue The handle to the queue from which the item is to be
* received.
*
* @param pvBuffer Pointer to the buffer into which the received item will
* be copied.
*
* @param xTicksToWait The maximum amount of time the task should block
* waiting for an item to receive should the queue be empty at the time
* of the call. The time is defined in tick periods so the constant
* portTICK_RATE_MS should be used to convert to real time if this is required.
*
* @return pdTRUE if an item was successfully received from the queue,
* otherwise pdFALSE.
*
* Example usage:
<pre>
struct AMessage
{
portCHAR ucMessageID;
portCHAR ucData[ 20 ];
} xMessage;
xQueueHandle xQueue;
// Task to create a queue and post a value.
void vATask( void *pvParameters )
{
struct AMessage *pxMessage;
// Create a queue capable of containing 10 pointers to AMessage structures.
// These should be passed by pointer as they contain a lot of data.
xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
if( xQueue == 0 )
{
// Failed to create the queue.
}
// ...
// Send a pointer to a struct AMessage object. Don't block if the
// queue is already full.
pxMessage = & xMessage;
xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );
// ... Rest of task code.
}

View File

@@ -0,0 +1,289 @@
/*
FreeRTOS.org V4.0.5 - Copyright (C) 2003-2006 Richard Barry.
This file is part of the FreeRTOS.org distribution.
FreeRTOS.org is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FreeRTOS.org is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FreeRTOS.org; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS.org, without being obliged to provide
the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details of how and when the exception
can be applied.
***************************************************************************
See http://www.FreeRTOS.org for documentation, latest information, license
and contact details. Please ensure to read the configuration and relevant
port sections of the online documentation.
***************************************************************************
*/
#include "queue.h"
#ifndef SEMAPHORE_H
#define SEMAPHORE_H
typedef xQueueHandle xSemaphoreHandle;
#define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( unsigned portCHAR ) 1 )
#define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned portCHAR ) 0 )
#define semGIVE_BLOCK_TIME ( ( portTickType ) 0 )
/**
* semphr. h
* <pre>vSemaphoreCreateBinary( xSemaphoreHandle xSemaphore )</pre>
*
* <i>Macro</i> that implements a semaphore by using the existing queue mechanism.
* The queue length is 1 as this is a binary semaphore. The data size is 0
* as we don't want to actually store any data - we just want to know if the
* queue is empty or full.
*
* @param xSemaphore Handle to the created semaphore. Should be of type xSemaphoreHandle.
*
* Example usage:
<pre>
xSemaphoreHandle xSemaphore;
void vATask( void * pvParameters )
{
// Semaphore cannot be used before a call to vSemaphoreCreateBinary ().
// This is a macro so pass the variable in directly.
vSemaphoreCreateBinary( xSemaphore );
if( xSemaphore != NULL )
{
// The semaphore was created successfully.
// The semaphore can now be used.
}
}
</pre>
* \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary
* \ingroup Semaphores
*/
#define vSemaphoreCreateBinary( xSemaphore ) { \
xSemaphore = xQueueCreate( ( unsigned portCHAR ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH ); \
if( xSemaphore != NULL ) \
{ \
xSemaphoreGive( xSemaphore ); \
} \
}
/**
* semphr. h
* xSemaphoreTake(
* xSemaphoreHandle xSemaphore,
* portTickType xBlockTime
* )</pre>
*
* <i>Macro</i> to obtain a semaphore. The semaphore must of been created using
* vSemaphoreCreateBinary ().
*
* @param xSemaphore A handle to the semaphore being obtained. This is the
* handle returned by vSemaphoreCreateBinary ();
*
* @param xBlockTime The time in ticks to wait for the semaphore to become
* available. The macro portTICK_RATE_MS can be used to convert this to a
* real time. A block time of zero can be used to poll the semaphore.
*
* @return pdTRUE if the semaphore was obtained. pdFALSE if xBlockTime
* expired without the semaphore becoming available.
*
* Example usage:
<pre>
xSemaphoreHandle xSemaphore = NULL;
// A task that creates a semaphore.
void vATask( void * pvParameters )
{
// Create the semaphore to guard a shared resource.
vSemaphoreCreateBinary( xSemaphore );
}
// A task that uses the semaphore.
void vAnotherTask( void * pvParameters )
{
// ... Do other things.
if( xSemaphore != NULL )
{
// See if we can obtain the semaphore. If the semaphore is not available
// wait 10 ticks to see if it becomes free.
if( xSemaphoreTake( xSemaphore, ( portTickType ) 10 ) == pdTRUE )
{
// We were able to obtain the semaphore and can now access the
// shared resource.
// ...
// We have finished accessing the shared resource. Release the
// semaphore.
xSemaphoreGive( xSemaphore );
}
else
{
// We could not obtain the semaphore and can therefore not access
// the shared resource safely.
}
}
}
</pre>
* \defgroup xSemaphoreTake xSemaphoreTake
* \ingroup Semaphores
*/

View File

@@ -0,0 +1,103 @@
/*
FreeRTOS.org V4.0.5 - Copyright (C) 2003-2006 Richard Barry.
This file is part of the FreeRTOS.org distribution.
FreeRTOS.org is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FreeRTOS.org is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FreeRTOS.org; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS.org, without being obliged to provide
the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details of how and when the exception
can be applied.
***************************************************************************
See http://www.FreeRTOS.org for documentation, latest information, license
and contact details. Please ensure to read the configuration and relevant
port sections of the online documentation.
***************************************************************************
*/
#ifndef SERIAL_COMMS_H
#define SERIAL_COMMS_H
typedef void * xComPortHandle;
typedef enum
{
serCOM1,
serCOM2,
serCOM3,
serCOM4,
serCOM5,
serCOM6,
serCOM7,
serCOM8
} eCOMPort;
typedef enum
{
serNO_PARITY,

View File

@@ -0,0 +1,926 @@
/*
FreeRTOS.org V4.0.5 - Copyright (C) 2003-2006 Richard Barry.
This file is part of the FreeRTOS.org distribution.
FreeRTOS.org is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FreeRTOS.org is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FreeRTOS.org; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS.org, without being obliged to provide
the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details of how and when the exception
can be applied.
***************************************************************************
See http://www.FreeRTOS.org for documentation, latest information, license
and contact details. Please ensure to read the configuration and relevant
port sections of the online documentation.
***************************************************************************
*/
#ifndef TASK_H
#define TASK_H
#include "portable.h"
#include "list.h"
/*-----------------------------------------------------------
* MACROS AND DEFINITIONS
*----------------------------------------------------------*/
#define tskKERNEL_VERSION_NUMBER "V4.0.5"
/**
* task. h
*
* Type by which tasks are referenced. For example, a call to xTaskCreate
* returns (via a pointer parameter) an xTaskHandle variable that can then
* be used as a parameter to vTaskDelete to delete the task.
*
* \page xTaskHandle xTaskHandle
* \ingroup Tasks
*/
typedef void * xTaskHandle;
/*
* Defines the priority used by the idle task. This must not be modified.
*
* \ingroup TaskUtils
*/
#define tskIDLE_PRIORITY ( ( unsigned portBASE_TYPE ) 0 )
/**
* task. h
*
* Macro for forcing a context switch.
*
* \page taskYIELD taskYIELD
* \ingroup SchedulerControl
*/
#define taskYIELD() portYIELD()
/**
* task. h
*
* Macro to mark the start of a critical code region. Preemptive context
* switches cannot occur when in a critical region.
*
* NOTE: This may alter the stack (depending on the portable implementation)
* so must be used with care!
*
* \page taskENTER_CRITICAL taskENTER_CRITICAL
* \ingroup SchedulerControl
*/
#define taskENTER_CRITICAL() portENTER_CRITICAL()
/**
* task. h
*
* Macro to mark the end of a critical code region. Preemptive context
* switches cannot occur when in a critical region.
*
* NOTE: This may alter the stack (depending on the portable implementation)
* so must be used with care!
*
* \page taskEXIT_CRITICAL taskEXIT_CRITICAL
* \ingroup SchedulerControl
*/
#define taskEXIT_CRITICAL() portEXIT_CRITICAL()
/**
* task. h
*
* Macro to disable all maskable interrupts.
*
* \page taskDISABLE_INTERRUPTS taskDISABLE_INTERRUPTS
* \ingroup SchedulerControl
*/
#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS()
/**
* task. h
*
* Macro to enable microcontroller interrupts.
*
* \page taskENABLE_INTERRUPTS taskENABLE_INTERRUPTS
* \ingroup SchedulerControl
*/
#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS()
/*-----------------------------------------------------------
* TASK CREATION API
*----------------------------------------------------------*/
/**
* task. h
*<pre>
portBASE_TYPE xTaskCreate(
pdTASK_CODE pvTaskCode,
const portCHAR * const pcName,
unsigned portSHORT usStackDepth,
void *pvParameters,
unsigned portBASE_TYPE uxPriority,
xTaskHandle *pvCreatedTask
);</pre>
*
* Create a new task and add it to the list of tasks that are ready to run.
*
* @param pvTaskCode Pointer to the task entry function. Tasks
* must be implemented to never return (i.e. continuous loop).
*
* @param pcName A descriptive name for the task. This is mainly used to
* facilitate debugging. Max length defined by tskMAX_TASK_NAME_LEN - default
* is 16.
*
* @param usStackDepth The size of the task stack specified as the number of
* variables the stack can hold - not the number of bytes. For example, if
* the stack is 16 bits wide and usStackDepth is defined as 100, 200 bytes
* will be allocated for stack storage.
*
* @param pvParameters Pointer that will be used as the parameter for the task
* being created.
*
* @param uxPriority The priority at which the task should run.
*
* @param pvCreatedTask Used to pass back a handle by which the created task
* can be referenced.
*
* @return pdPASS if the task was successfully created and added to a ready
* list, otherwise an error code defined in the file errors. h
*
* Example usage:
<pre>
// Task to be created.
void vTaskCode( void * pvParameters )
{
for( ;; )
{
// Task code goes here.
}
}
// Function that creates a task.
void vOtherFunction( void )
{
unsigned char ucParameterToPass;
xTaskHandle xHandle;
// Create the task, storing the handle.
xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle );
// Use the handle to delete the task.
vTaskDelete( xHandle );
}
</pre>
* \defgroup xTaskCreate xTaskCreate
* \ingroup Tasks
*/
signed portBASE_TYPE xTaskCreate( pdTASK_CODE pvTaskCode, const signed portCHAR * const pcName, unsigned portSHORT usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pvCreatedTask );
/**
* task. h
* <pre>void vTaskDelete( xTaskHandle pxTask );</pre>
*
* INCLUDE_vTaskDelete must be defined as 1 for this function to be available.
* See the configuration section for more information.
*
* Remove a task from the RTOS real time kernels management. The task being
* deleted will be removed from all ready, blocked, suspended and event lists.
*
* NOTE: The idle task is responsible for freeing the kernel allocated
* memory from tasks that have been deleted. It is therefore important that
* the idle task is not starved of microcontroller processing time if your
* application makes any calls to vTaskDelete (). Memory allocated by the
* task code is not automatically freed, and should be freed before the task
* is deleted.
*
* See the demo application file death.c for sample code that utilises
* vTaskDelete ().
*
* @param pxTask The handle of the task to be deleted. Passing NULL will
* cause the calling task to be deleted.
*
* Example usage:
<pre>
void vOtherFunction( void )
{
xTaskHandle xHandle;
// Create the task, storing the handle.
xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
// Use the handle to delete the task.
vTaskDelete( xHandle );
}
</pre>
* \defgroup vTaskDelete vTaskDelete
* \ingroup Tasks
*/
void vTaskDelete( xTaskHandle pxTask );
/*-----------------------------------------------------------
* TASK CONTROL API
*----------------------------------------------------------*/
/**
* task. h
* <pre>void vTaskDelay( portTickType xTicksToDelay );</pre>
*
* Delay a task for a given number of ticks. The actual time that the
* task remains blocked depends on the tick rate. The constant
* portTICK_RATE_MS can be used to calculate real time from the tick
* rate - with the resolution of one tick period.
*
* INCLUDE_vTaskDelay must be defined as 1 for this function to be available.
* See the configuration section for more information.
*
* @param xTicksToDelay The amount of time, in tick periods, that
* the calling task should block.
*
* Example usage:
<pre>
// Wait 10 ticks before performing an action.
// NOTE:
// This is for demonstration only and would be better achieved
// using vTaskDelayUntil ().
void vTaskFunction( void * pvParameters )
{
portTickType xDelay, xNextTime;
// Calc the time at which we want to perform the action
// next.
xNextTime = xTaskGetTickCount () + ( portTickType ) 10;
for( ;; )
{
xDelay = xNextTime - xTaskGetTickCount ();
xNextTime += ( portTickType ) 10;
// Guard against overflow
if( xDelay <= ( portTickType ) 10 )
{
vTaskDelay( xDelay );
}
// Perform action here.
}
}
</pre>
* \defgroup vTaskDelay vTaskDelay
* \ingroup TaskCtrl
*/
void vTaskDelay( portTickType xTicksToDelay );
/**
* task. h
* <pre>void vTaskDelayUntil( portTickType *pxPreviousWakeTime, portTickType xTimeIncrement );</pre>
*
* INCLUDE_vTaskDelayUntil must be defined as 1 for this function to be available.
* See the configuration section for more information.
*
* Delay a task until a specified time. This function can be used by cyclical
* tasks to ensure a constant execution frequency.
*
* This function differs from vTaskDelay () in one important aspect: vTaskDelay () will
* cause a task to block for the specified number of ticks from the time vTaskDelay () is
* called. It is therefore difficult to use vTaskDelay () by itself to generate a fixed
* execution frequency as the time between a task starting to execute and that task
* calling vTaskDelay () may not be fixed [the task may take a different path though the
* code between calls, or may get interrupted or preempted a different number of times
* each time it executes].
*
* Whereas vTaskDelay () specifies a wake time relative to the time at which the function
* is called, vTaskDelayUntil () specifies the absolute (exact) time at which it wishes to
* unblock.
*
* The constant portTICK_RATE_MS can be used to calculate real time from the tick
* rate - with the resolution of one tick period.
*
* @param pxPreviousWakeTime Pointer to a variable that holds the time at which the
* task was last unblocked. The variable must be initialised with the current time
* prior to its first use (see the example below). Following this the variable is
* automatically updated within vTaskDelayUntil ().
*
* @param xTimeIncrement The cycle time period. The task will be unblocked at
* time *pxPreviousWakeTime + xTimeIncrement. Calling vTaskDelayUntil with the
* same xTimeIncrement parameter value will cause the task to execute with
* a fixed interface period.
*
* Example usage:
<pre>
// Perform an action every 10 ticks.
void vTaskFunction( void * pvParameters )
{
portTickType xLastWakeTime;
const portTickType xFrequency = 10;
// Initialise the xLastWakeTime variable with the current time.
xLastWakeTime = xTaskGetTickCount ();
for( ;; )
{
// Wait for the next cycle.
vTaskDelayUntil( &xLastWakeTime, xFrequency );
// Perform action here.
}
}
</pre>
* \defgroup vTaskDelayUntil vTaskDelayUntil
* \ingroup TaskCtrl
*/
void vTaskDelayUntil( portTickType *pxPreviousWakeTime, portTickType xTimeIncrement );
/**
* task. h
* <pre>unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask );</pre>
*
* INCLUDE_xTaskPriorityGet must be defined as 1 for this function to be available.
* See the configuration section for more information.
*
* Obtain the priority of any task.
*
* @param pxTask Handle of the task to be queried. Passing a NULL
* handle results in the priority of the calling task being returned.
*
* @return The priority of pxTask.
*
* Example usage:
<pre>
void vAFunction( void )
{
xTaskHandle xHandle;
// Create a task, storing the handle.
xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
// ...
// Use the handle to obtain the priority of the created task.
// It was created with tskIDLE_PRIORITY, but may have changed
// it itself.
if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY )
{
// The task has changed it's priority.
}
// ...
// Is our priority higher than the created task?
if( uxTaskPriorityGet( xHandle ) < uxTaskPriorityGet( NULL ) )
{
// Our priority (obtained using NULL handle) is higher.
}
}
</pre>
* \defgroup uxTaskPriorityGet uxTaskPriorityGet
* \ingroup TaskCtrl
*/
unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask );
/**
* task. h
* <pre>void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority );</pre>
*
* INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be available.
* See the configuration section for more information.
*
* Set the priority of any task.
*
* A context switch will occur before the function returns if the priority
* being set is higher than the currently executing task.
*
* @param pxTask Handle to the task for which the priority is being set.
* Passing a NULL handle results in the priority of the calling task being set.
*
* @param uxNewPriority The priority to which the task will be set.
*
* Example usage:
<pre>
void vAFunction( void )
{
xTaskHandle xHandle;
// Create a task, storing the handle.
xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
// ...
// Use the handle to raise the priority of the created task.
vTaskPrioritySet( xHandle, tskIDLE_PRIORITY + 1 );
// ...
// Use a NULL handle to raise our priority to the same value.
vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 );
}
</pre>
* \defgroup vTaskPrioritySet vTaskPrioritySet
* \ingroup TaskCtrl
*/
void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority );
/**
* task. h
* <pre>void vTaskSuspend( xTaskHandle pxTaskToSuspend );</pre>
*
* INCLUDE_vTaskSuspend must be defined as 1 for this function to be available.
* See the configuration section for more information.
*
* Suspend any task. When suspended a task will never get any microcontroller
* processing time, no matter what its priority.
*
* Calls to vTaskSuspend are not accumulative -
* i.e. calling vTaskSuspend () twice on the same task still only requires one
* call to vTaskResume () to ready the suspended task.
*
* @param pxTaskToSuspend Handle to the task being suspended. Passing a NULL
* handle will cause the calling task to be suspended.
*
* Example usage:
<pre>
void vAFunction( void )
{
xTaskHandle xHandle;
// Create a task, storing the handle.
xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
// ...

View File

@@ -0,0 +1,201 @@
/*
FreeRTOS.org V4.0.5 - Copyright (C) 2003-2006 Richard Barry.
This file is part of the FreeRTOS.org distribution.
FreeRTOS.org is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FreeRTOS.org is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FreeRTOS.org; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS.org, without being obliged to provide
the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details of how and when the exception
can be applied.
***************************************************************************
See http://www.FreeRTOS.org for documentation, latest information, license
and contact details. Please ensure to read the configuration and relevant
port sections of the online documentation.
***************************************************************************
*/
/*
Changes from V1.2.0
+ Removed the volatile modifier from the function parameters. This was
only ever included to prevent compiler warnings. Now warnings are
removed by casting parameters where the calls are made.
+ prvListGetOwnerOfNextEntry() and prvListGetOwnerOfHeadEntry() have been
removed from the c file and added as macros to the h file.
+ uxNumberOfItems has been added to the list structure. This removes the
need for a pointer comparison when checking if a list is empty, and so
is slightly faster.
+ Removed the NULL check in vListRemove(). This makes the call faster but
necessitates any application code utilising the list implementation to
ensure NULL pointers are not passed.
Changes from V2.0.0
+ Double linked the lists to allow faster removal item removal.
Changes from V2.6.1
+ Make use of the new portBASE_TYPE definition where ever appropriate.
Changes from V3.0.0
+ API changes as described on the FreeRTOS.org WEB site.
Changes from V3.2.4
+ Removed the pxHead member of the xList structure. This always pointed
to the same place so has been removed to free a few bytes of RAM.
+ Introduced the xMiniListItem structure that does not include the
xListItem members that are not required by the xListEnd member of a list.
Again this was done to reduce RAM usage.
+ Changed the volatile definitions of some structure members to clean up
the code where the list structures are used.
Changes from V4.0.4
+ Optimised vListInsert() in the case when the wake time is the maximum
tick count value.
*/
#include <stdlib.h>
#include "FreeRTOS.h"
#include "list.h"
/*-----------------------------------------------------------
* PUBLIC LIST API documented in list.h
*----------------------------------------------------------*/
void vListInitialise( xList *pxList )
{
/* The list structure contains a list item which is used to mark the
end of the list. To initialise the list the list end is inserted
as the only list entry. */
pxList->pxIndex = ( xListItem * ) &( pxList->xListEnd );
/* The list end value is the highest possible value in the list to
ensure it remains at the end of the list. */
pxList->xListEnd.xItemValue = portMAX_DELAY;
/* The list end next and previous pointers point to itself so we know
when the list is empty. */

View File

@@ -0,0 +1,263 @@
/*
FreeRTOS V4.0.1 - Copyright (C) 2003-2006 Richard Barry.
MCF5235 Port - Copyright (C) 2006 Christian Walter.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FreeRTOS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FreeRTOS; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS, without being obliged to provide
the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details of how and when the exception
can be applied.
***************************************************************************
See http://www.FreeRTOS.org for documentation, latest information, license
and contact details. Please ensure to read the configuration and relevant
port sections of the online documentation.
***************************************************************************
*/
#include <stdlib.h>
#include "FreeRTOS.h"
#include "FreeRTOSConfig.h"
#include "task.h"
/* ------------------------ Types ----------------------------------------- */
typedef volatile unsigned long vuint32;
typedef volatile unsigned short vuint16;
typedef volatile unsigned char vuint8;
/* ------------------------ Defines --------------------------------------- */
#define portVECTOR_TABLE __RAMVEC
#define portVECTOR_SYSCALL ( 32 + portTRAP_YIELD )
#define portVECTOR_TIMER ( 64 + 36 )
#define MCF_PIT_PRESCALER 512UL
#define MCF_PIT_TIMER_TICKS ( FSYS_2 / MCF_PIT_PRESCALER )
#define MCF_PIT_MODULUS_REGISTER(freq) ( MCF_PIT_TIMER_TICKS / ( freq ) - 1UL)
#define MCF_PIT_PMR0 ( *( vuint16 * )( void * )( &__IPSBAR[ 0x150002 ] ) )
#define MCF_PIT_PCSR0 ( *( vuint16 * )( void * )( &__IPSBAR[ 0x150000 ] ) )
#define MCF_PIT_PCSR_PRE(x) ( ( ( x ) & 0x000F ) << 8 )
#define MCF_PIT_PCSR_EN ( 0x0001 )
#define MCF_PIT_PCSR_RLD ( 0x0002 )
#define MCF_PIT_PCSR_PIF ( 0x0004 )
#define MCF_PIT_PCSR_PIE ( 0x0008 )
#define MCF_PIT_PCSR_OVW ( 0x0010 )
#define MCF_INTC0_ICR36 ( *( vuint8 * )( void * )( &__IPSBAR[ 0x000C64 ] ) )
#define MCF_INTC0_IMRH ( *( vuint32 * )( void * )( &__IPSBAR[ 0x000C08 ] ) )
#define MCF_INTC0_IMRH_INT_MASK36 ( 0x00000010 )
#define MCF_INTC0_IMRH_MASKALL ( 0x00000001 )
#define MCF_INTC0_ICRn_IP(x) ( ( ( x ) & 0x07 ) << 0 )
#define MCF_INTC0_ICRn_IL(x) ( ( ( x ) & 0x07 ) << 3 )
#define portNO_CRITICAL_NESTING ( ( unsigned portLONG ) 0 )
#define portINITIAL_CRITICAL_NESTING ( ( unsigned portLONG ) 10 )
/* ------------------------ Static variables ------------------------------ */
volatile unsigned portLONG ulCriticalNesting = portINITIAL_CRITICAL_NESTING;
/* ------------------------ Static functions ------------------------------ */
#if configUSE_PREEMPTION == 0
static void prvPortPreemptiveTick ( void ) __attribute__ ((interrupt_handler));
#else
static void prvPortPreemptiveTick ( void );
#endif
/* ------------------------ Start implementation -------------------------- */
portSTACK_TYPE *
pxPortInitialiseStack( portSTACK_TYPE * pxTopOfStack, pdTASK_CODE pxCode,
void *pvParameters )
{
/* Place the parameter on the stack in the expected location. */
*pxTopOfStack = ( portSTACK_TYPE ) pvParameters;
pxTopOfStack--;
/* Place dummy return address on stack. Tasks should never terminate so
* we can set this to anything. */
*pxTopOfStack = ( portSTACK_TYPE ) 0;
pxTopOfStack--;
/* Create a Motorola Coldfire exception stack frame. First comes the return
* address. */
*pxTopOfStack = ( portSTACK_TYPE ) pxCode;
pxTopOfStack--;
/* Format, fault-status, vector number for exception stack frame. Task
* run in supervisor mode. */
*pxTopOfStack = 0x40002000UL | ( portVECTOR_SYSCALL + 32 ) << 18;
pxTopOfStack--;
/* Set the initial critical section nesting counter to zero. This value
* is used to restore the value of ulCriticalNesting. */
*pxTopOfStack = 0;
*pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0xA6; /* A6 / FP */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0xA5; /* A5 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0xA4; /* A4 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0xA3; /* A3 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0xA2; /* A2 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0xA1; /* A1 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0xA0; /* A0 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0xD7; /* D7 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0xD6; /* D6 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0xD5; /* D5 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0xD4; /* D4 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0xD3; /* D3 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0xD2; /* D2 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0xD1; /* D1 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0xD0; /* D0 */
return pxTopOfStack;
}
/*
* Called by portYIELD() or taskYIELD() to manually force a context switch.
*/
static void
prvPortYield( void )
{
asm volatile ( "move.w #0x2700, %sr\n\t" );
#if _GCC_USES_FP == 1
asm volatile ( "unlk %fp\n\t" );
#endif
/* Perform the context switch. First save the context of the current task. */
portSAVE_CONTEXT( );
/* Find the highest priority task that is ready to run. */
vTaskSwitchContext( );
/* Restore the context of the new task. */
portRESTORE_CONTEXT( );
}
#if configUSE_PREEMPTION == 0
/*
* The ISR used for the scheduler tick depends on whether the cooperative or
* the preemptive scheduler is being used.
*/
static void
prvPortPreemptiveTick ( void )
{
/* The cooperative scheduler requires a normal IRQ service routine to
* simply increment the system tick.
*/
vTaskIncrementTick( );
MCF_PIT_PCSR0 |= MCF_PIT_PCSR_PIF;
}
#else
static void
prvPortPreemptiveTick( void )
{
asm volatile ( "move.w #0x2700, %sr\n\t" );
#if _GCC_USES_FP == 1
asm volatile ( "unlk %fp\n\t" );
#endif
portSAVE_CONTEXT( );
MCF_PIT_PCSR0 |= MCF_PIT_PCSR_PIF;
vTaskIncrementTick( );
vTaskSwitchContext( );
portRESTORE_CONTEXT( );
}
#endif
void
vPortEnterCritical()
{
/* FIXME: We should store the old IPL here - How are we supposed to do
* this.
*/
( void )portSET_IPL( portIPL_MAX );
/* Now interrupts are disabled ulCriticalNesting can be accessed
* directly. Increment ulCriticalNesting to keep a count of how many times
* portENTER_CRITICAL() has been called. */
ulCriticalNesting++;
}
void
vPortExitCritical()
{
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
{
/* Decrement the nesting count as we are leaving a critical section. */
ulCriticalNesting--;
/* If the nesting level has reached zero then interrupts should be
re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{
( void )portSET_IPL( 0 );
}
}
}
portBASE_TYPE
xPortStartScheduler( void )
{
extern void ( *portVECTOR_TABLE[ ] ) ( );
/* Add entry in vector table for yield system call. */
portVECTOR_TABLE[ portVECTOR_SYSCALL ] = prvPortYield;
/* Add entry in vector table for periodic timer. */
portVECTOR_TABLE[ portVECTOR_TIMER ] = prvPortPreemptiveTick;
/* Configure the timer for the system clock. */
if ( configTICK_RATE_HZ > 0)
{
/* Configure prescaler */
MCF_PIT_PCSR0 = MCF_PIT_PCSR_PRE( 0x9 ) | MCF_PIT_PCSR_RLD | MCF_PIT_PCSR_OVW;
/* Initialize the periodic timer interrupt. */
MCF_PIT_PMR0 = MCF_PIT_MODULUS_REGISTER( configTICK_RATE_HZ );
/* Configure interrupt priority and level and unmask interrupt. */
MCF_INTC0_ICR36 = MCF_INTC0_ICRn_IL( 0x1 ) | MCF_INTC0_ICRn_IP( 0x1 );
MCF_INTC0_IMRH &= ~( MCF_INTC0_IMRH_INT_MASK36 | MCF_INTC0_IMRH_MASKALL );
/* Enable interrupts */
MCF_PIT_PCSR0 |= MCF_PIT_PCSR_PIE | MCF_PIT_PCSR_EN | MCF_PIT_PCSR_PIF;
}
/* Restore the context of the first task that is going to run. */
portRESTORE_CONTEXT( );
/* Should not get here. */
return pdTRUE;
}
void
vPortEndScheduler( void )
{
}

View File

@@ -0,0 +1,132 @@
/*
FreeRTOS.org V4.0.5 - Copyright (C) 2003-2006 Richard Barry.
This file is part of the FreeRTOS.org distribution.
FreeRTOS.org is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FreeRTOS.org is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FreeRTOS.org; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS.org, without being obliged to provide
the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details of how and when the exception
can be applied.
***************************************************************************
See http://www.FreeRTOS.org for documentation, latest information, license
and contact details. Please ensure to read the configuration and relevant
port sections of the online documentation.
***************************************************************************
*/
/*
Changes between V2.5.1 and V2.5.1
+ The memory pool has been defined within a struct to ensure correct memory
alignment on 32bit systems.
Changes between V2.6.1 and V3.0.0
+ An overflow check has been added to ensure the next free byte variable
does not wrap around.
*/
/*
* The simplest possible implementation of pvPortMalloc(). Note that this
* implementation does NOT allow allocated memory to be freed again.
*
* See heap_2.c and heap_3.c for alternative implementations, and the memory
* management pages of http://www.FreeRTOS.org for more information.
*/
#include <stdlib.h>
#include "FreeRTOS.h"
#include "task.h"
/* Setup the correct byte alignment mask for the defined byte alignment. */
#if portBYTE_ALIGNMENT == 4
#define heapBYTE_ALIGNMENT_MASK ( ( size_t ) 0x0003 )
#endif
#if portBYTE_ALIGNMENT == 2
#define heapBYTE_ALIGNMENT_MASK ( ( size_t ) 0x0001 )
#endif

View File

@@ -0,0 +1,236 @@
/*
FreeRTOS.org V4.0.5 - Copyright (C) 2003-2006 Richard Barry.
This file is part of the FreeRTOS.org distribution.
FreeRTOS.org is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FreeRTOS.org is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FreeRTOS.org; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS.org, without being obliged to provide
the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details of how and when the exception
can be applied.
***************************************************************************
See http://www.FreeRTOS.org for documentation, latest information, license
and contact details. Please ensure to read the configuration and relevant
port sections of the online documentation.
***************************************************************************
*/
/*
* A sample implementation of pvPortMalloc() and vPortFree() that permits
* allocated blocks to be freed, but does not combine adjacent free blocks
* into a single larger block.
*
* See heap_1.c and heap_3.c for alternative implementations, and the memory
* management pages of http://www.FreeRTOS.org for more information.
*/
#include <stdlib.h>
#include "FreeRTOS.h"
#include "task.h"
/* Setup the correct byte alignment mask for the defined byte alignment. */
#if portBYTE_ALIGNMENT == 4
#define heapBYTE_ALIGNMENT_MASK ( ( size_t ) 0x0003 )
#endif
#if portBYTE_ALIGNMENT == 2
#define heapBYTE_ALIGNMENT_MASK ( ( size_t ) 0x0001 )
#endif
#if portBYTE_ALIGNMENT == 1
#define heapBYTE_ALIGNMENT_MASK ( ( size_t ) 0x0000 )
#endif
#ifndef heapBYTE_ALIGNMENT_MASK
#error "Invalid portBYTE_ALIGNMENT definition"
#endif
/* Allocate the memory for the heap. The struct is used to force byte
alignment without using any non-portable code. */
static struct xRTOS_HEAP
{
unsigned portLONG ulDummy;
unsigned portCHAR ucHeap[ configTOTAL_HEAP_SIZE ];
} xHeap;
/* Define the linked list structure. This is used to link free blocks in order
of their size. */
typedef struct A_BLOCK_LINK
{
struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */
size_t xBlockSize; /*<< The size of the free block. */
} xBlockLink;
static const unsigned portSHORT heapSTRUCT_SIZE = ( sizeof( xBlockLink ) + ( sizeof( xBlockLink ) % portBYTE_ALIGNMENT ) );
#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( heapSTRUCT_SIZE * 2 ) )
/* Create a couple of list links to mark the start and end of the list. */
static xBlockLink xStart, xEnd;
/* STATIC FUNCTIONS ARE DEFINED AS MACROS TO MINIMIZE THE FUNCTION CALL DEPTH. */
/*
* Insert a block into the list of free blocks - which is ordered by size of
* the block. Small blocks at the start of the list and large blocks at the end
* of the list.
*/
#define prvInsertBlockIntoFreeList( pxBlockToInsert ) \
{ \
xBlockLink *pxIterator; \
size_t xBlockSize; \
\
xBlockSize = pxBlockToInsert->xBlockSize; \
\
/* Iterate through the list until a block is found that has a larger size */ \
/* than the block we are inserting. */ \
for( pxIterator = &xStart; pxIterator->pxNextFreeBlock->xBlockSize < xBlockSize; pxIterator = pxIterator->pxNextFreeBlock ) \
{ \
/* There is nothing to do here - just iterate to the correct position. */ \
} \
\
/* Update the list to include the block being inserted in the correct */ \
/* position. */ \
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock; \
pxIterator->pxNextFreeBlock = pxBlockToInsert; \
}
/*-----------------------------------------------------------*/
#define prvHeapInit() \
{ \
xBlockLink *pxFirstFreeBlock; \
\
/* xStart is used to hold a pointer to the first item in the list of free */ \

View File

@@ -0,0 +1,79 @@
/*
FreeRTOS.org V4.0.5 - Copyright (C) 2003-2006 Richard Barry.
This file is part of the FreeRTOS.org distribution.
FreeRTOS.org is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FreeRTOS.org is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FreeRTOS.org; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS.org, without being obliged to provide
the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details of how and when the exception
can be applied.
***************************************************************************
See http://www.FreeRTOS.org for documentation, latest information, license
and contact details. Please ensure to read the configuration and relevant
port sections of the online documentation.
***************************************************************************
*/
/*
* Implementation of pvPortMalloc() and vPortFree() that relies on the
* compilers own malloc() and free() implementations.
*
* This file can only be used if the linker is configured to to generate
* a heap memory area.
*

View File

@@ -0,0 +1,869 @@
/*
FreeRTOS.org V4.0.5 - Copyright (C) 2003-2006 Richard Barry.
This file is part of the FreeRTOS.org distribution.
FreeRTOS.org is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FreeRTOS.org is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FreeRTOS.org; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS.org, without being obliged to provide
the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details of how and when the exception
can be applied.
***************************************************************************
See http://www.FreeRTOS.org for documentation, latest information, license
and contact details. Please ensure to read the configuration and relevant
port sections of the online documentation.
***************************************************************************
*/
/*
Changes from V1.01
+ More use of 8bit data types.
+ Function name prefixes changed where the data type returned has changed.
Changed from V2.0.0
+ Added the queue locking mechanism and make more use of the scheduler
suspension feature to minimise the time interrupts have to be disabled
when accessing a queue.
Changed from V2.2.0
+ Explicit use of 'signed' qualifier on portCHAR types added.
Changes from V3.0.0
+ API changes as described on the FreeRTOS.org WEB site.
Changes from V3.2.3
+ Added the queue functions that can be used from co-routines.
*/
#include <stdlib.h>
#include <string.h>
#include "FreeRTOS.h"
#include "task.h"
#include "croutine.h"
/*-----------------------------------------------------------
* PUBLIC LIST API documented in list.h
*----------------------------------------------------------*/
/* Constants used with the cRxLock and cTxLock structure members. */
#define queueUNLOCKED ( ( signed portBASE_TYPE ) -1 )
/*
* Definition of the queue used by the scheduler.
* Items are queued by copy, not reference.
*/
typedef struct QueueDefinition
{
signed portCHAR *pcHead; /*< Points to the beginning of the queue storage area. */
signed portCHAR *pcTail; /*< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */
signed portCHAR *pcWriteTo; /*< Points to the free next place in the storage area. */
signed portCHAR *pcReadFrom; /*< Points to the last place that a queued item was read from. */
xList xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */
xList xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */
unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */
unsigned portBASE_TYPE uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
unsigned portBASE_TYPE uxItemSize; /*< The size of each items that the queue will hold. */
signed portBASE_TYPE xRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */
signed portBASE_TYPE xTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */
} xQUEUE;
/*-----------------------------------------------------------*/
/*
* Inside this file xQueueHandle is a pointer to a xQUEUE structure.
* To keep the definition private the API header file defines it as a
* pointer to void.
*/
typedef xQUEUE * xQueueHandle;
/*
* Prototypes for public functions are included here so we don't have to
* include the API header file (as it defines xQueueHandle differently). These
* functions are documented in the API header file.
*/
xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize );
signed portBASE_TYPE xQueueSend( xQueueHandle xQueue, const void * pvItemToQueue, portTickType xTicksToWait );
unsigned portBASE_TYPE uxQueueMessagesWaiting( xQueueHandle pxQueue );
void vQueueDelete( xQueueHandle xQueue );
signed portBASE_TYPE xQueueSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken );
signed portBASE_TYPE xQueueReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait );
signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken );
#if configUSE_CO_ROUTINES == 1
signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken );
signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken );
signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait );
signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait );
#endif
/*
* Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not
* prevent an ISR from adding or removing items to the queue, but does prevent
* an ISR from removing tasks from the queue event lists. If an ISR finds a
* queue is locked it will instead increment the appropriate queue lock count
* to indicate that a task may require unblocking. When the queue in unlocked
* these lock counts are inspected, and the appropriate action taken.
*/
static signed portBASE_TYPE prvUnlockQueue( xQueueHandle pxQueue );
/*
* Uses a critical section to determine if there is any data in a queue.
*
* @return pdTRUE if the queue contains no items, otherwise pdFALSE.
*/
static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue );
/*
* Uses a critical section to determine if there is any space in a queue.
*
* @return pdTRUE if there is no space, otherwise pdFALSE;
*/
static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue );
/*
* Macro that copies an item into the queue. This is done by copying the item
* byte for byte, not by reference. Updates the queue state to ensure it's
* integrity after the copy.
*/
#define prvCopyQueueData( pxQueue, pvItemToQueue ) \
{ \
memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize ); \
++( pxQueue->uxMessagesWaiting ); \
pxQueue->pcWriteTo += pxQueue->uxItemSize; \
if( pxQueue->pcWriteTo >= pxQueue->pcTail ) \
{ \
pxQueue->pcWriteTo = pxQueue->pcHead; \
} \
}
/*-----------------------------------------------------------*/
/*
* Macro to mark a queue as locked. Locking a queue prevents an ISR from
* accessing the queue event lists.
*/
#define prvLockQueue( pxQueue ) \
{ \
taskENTER_CRITICAL(); \
++( pxQueue->xRxLock ); \
++( pxQueue->xTxLock ); \
taskEXIT_CRITICAL(); \
}
/*-----------------------------------------------------------*/
/*-----------------------------------------------------------
* PUBLIC QUEUE MANAGEMENT API documented in queue.h
*----------------------------------------------------------*/
xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize )
{
xQUEUE *pxNewQueue;
size_t xQueueSizeInBytes;
/* Allocate the new queue structure. */
if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 )
{
pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
if( pxNewQueue != NULL )
{
/* Create the list of pointers to queue items. The queue is one byte
longer than asked for to make wrap checking easier/faster. */
xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1;
pxNewQueue->pcHead = ( signed portCHAR * ) pvPortMalloc( xQueueSizeInBytes );
if( pxNewQueue->pcHead != NULL )
{
/* Initialise the queue members as described above where the
queue type is defined. */
pxNewQueue->pcTail = pxNewQueue->pcHead + ( uxQueueLength * uxItemSize );
pxNewQueue->uxMessagesWaiting = 0;
pxNewQueue->pcWriteTo = pxNewQueue->pcHead;
pxNewQueue->pcReadFrom = pxNewQueue->pcHead + ( ( uxQueueLength - 1 ) * uxItemSize );
pxNewQueue->uxLength = uxQueueLength;
pxNewQueue->uxItemSize = uxItemSize;
pxNewQueue->xRxLock = queueUNLOCKED;
pxNewQueue->xTxLock = queueUNLOCKED;
/* Likewise ensure the event queues start with the correct state. */
vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
return pxNewQueue;
}
else
{
vPortFree( pxNewQueue );
}
}
}
/* Will only reach here if we could not allocate enough memory or no memory
was required. */
return NULL;
}
/*-----------------------------------------------------------*/
signed portBASE_TYPE xQueueSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait )
{
signed portBASE_TYPE xReturn;
/* Make sure other tasks do not access the queue. */
vTaskSuspendAll();
/* It is important that this is the only thread/ISR that modifies the
ready or delayed lists until xTaskResumeAll() is called. Places where
the ready/delayed lists are modified include:
+ vTaskDelay() - Nothing can call vTaskDelay as the scheduler is
suspended, vTaskDelay() cannot be called from an ISR.
+ vTaskPrioritySet() - Has a critical section around the access.
+ vTaskSwitchContext() - This will not get executed while the scheduler
is suspended.
+ prvCheckDelayedTasks() - This will not get executed while the
scheduler is suspended.
+ xTaskCreate() - Has a critical section around the access.
+ vTaskResume() - Has a critical section around the access.
+ xTaskResumeAll() - Has a critical section around the access.
+ xTaskRemoveFromEventList - Checks to see if the scheduler is
suspended. If so then the TCB being removed from the event is
removed from the event and added to the xPendingReadyList.
*/
/* Make sure interrupts do not access the queue event list. */
prvLockQueue( pxQueue );
/* It is important that interrupts to not access the event list of the
queue being modified here. Places where the event list is modified
include:
+ xQueueSendFromISR(). This checks the lock on the queue to see if
it has access. If the queue is locked then the Tx lock count is
incremented to signify that a task waiting for data can be made ready
once the queue lock is removed. If the queue is not locked then
a task can be moved from the event list, but will not be removed
from the delayed list or placed in the ready list until the scheduler
is unlocked.
+ xQueueReceiveFromISR(). As per xQueueSendFromISR().
*/
/* If the queue is already full we may have to block. */
if( prvIsQueueFull( pxQueue ) )
{
/* The queue is full - do we want to block or just leave without
posting? */
if( xTicksToWait > ( portTickType ) 0 )
{
/* We are going to place ourselves on the xTasksWaitingToSend event
list, and will get woken should the delay expire, or space become
available on the queue.
As detailed above we do not require mutual exclusion on the event
list as nothing else can modify it or the ready lists while we
have the scheduler suspended and queue locked.
It is possible that an ISR has removed data from the queue since we
checked if any was available. If this is the case then the data
will have been copied from the queue, and the queue variables
updated, but the event list will not yet have been checked to see if
anything is waiting as the queue is locked. */
vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
/* Force a context switch now as we are blocked. We can do
this from within a critical section as the task we are
switching to has its own context. When we return here (i.e. we
unblock) we will leave the critical section as normal.
It is possible that an ISR has caused an event on an unrelated and
unlocked queue. If this was the case then the event list for that
queue will have been updated but the ready lists left unchanged -
instead the readied task will have been added to the pending ready
list. */
taskENTER_CRITICAL();
{
/* We can safely unlock the queue and scheduler here as
interrupts are disabled. We must not yield with anything
locked, but we can yield from within a critical section.
Tasks that have been placed on the pending ready list cannot
be tasks that are waiting for events on this queue. See
in comment xTaskRemoveFromEventList(). */
prvUnlockQueue( pxQueue );
/* Resuming the scheduler may cause a yield. If so then there
is no point yielding again here. */
if( !xTaskResumeAll() )
{
taskYIELD();
}
/* Before leaving the critical section we have to ensure
exclusive access again. */
vTaskSuspendAll();
prvLockQueue( pxQueue );
}
taskEXIT_CRITICAL();
}
}
/* When we are here it is possible that we unblocked as space became
available on the queue. It is also possible that an ISR posted to the
queue since we left the critical section, so it may be that again there
is no space. This would only happen if a task and ISR post onto the
same queue. */
taskENTER_CRITICAL();
{
if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
{
/* There is room in the queue, copy the data into the queue. */
prvCopyQueueData( pxQueue, pvItemToQueue );
xReturn = pdPASS;
/* Update the TxLock count so prvUnlockQueue knows to check for
tasks waiting for data to become available in the queue. */
++( pxQueue->xTxLock );
}
else
{
xReturn = errQUEUE_FULL;
}
}
taskEXIT_CRITICAL();
/* We no longer require exclusive access to the queue. prvUnlockQueue
will remove any tasks suspended on a receive if either this function
or an ISR has posted onto the queue. */
if( prvUnlockQueue( pxQueue ) )
{
/* Resume the scheduler - making ready any tasks that were woken
by an event while the scheduler was locked. Resuming the
scheduler may cause a yield, in which case there is no point
yielding again here. */
if( !xTaskResumeAll() )
{
taskYIELD();
}
}
else
{
/* Resume the scheduler - making ready any tasks that were woken
by an event while the scheduler was locked. */
xTaskResumeAll();
}
return xReturn;
}
/*-----------------------------------------------------------*/
signed portBASE_TYPE xQueueSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken )
{
/* Similar to xQueueSend, except we don't block if there is no room in the
queue. Also we don't directly wake a task that was blocked on a queue
read, instead we return a flag to say whether a context switch is required
or not (i.e. has a task with a higher priority than us been woken by this
post). */
if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
{
prvCopyQueueData( pxQueue, pvItemToQueue );
/* If the queue is locked we do not alter the event list. This will
be done when the queue is unlocked later. */
if( pxQueue->xTxLock == queueUNLOCKED )
{
/* We only want to wake one task per ISR, so check that a task has
not already been woken. */
if( !xTaskPreviouslyWoken )
{
if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
{
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
{
/* The task waiting has a higher priority so record that a
context switch is required. */
return pdTRUE;
}
}
}
}
else
{
/* Increment the lock count so the task that unlocks the queue
knows that data was posted while it was locked. */
++( pxQueue->xTxLock );
}
}
return xTaskPreviouslyWoken;
}
/*-----------------------------------------------------------*/
signed portBASE_TYPE xQueueReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait )
{
signed portBASE_TYPE xReturn;
/* This function is very similar to xQueueSend(). See comments within
xQueueSend() for a more detailed explanation.
Make sure other tasks do not access the queue. */
vTaskSuspendAll();
/* Make sure interrupts do not access the queue. */
prvLockQueue( pxQueue );

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,40 @@
/*
* File: mcf523x.h
* Purpose: Register and bit definitions for the MCF523X
*
* Notes:
*
*/
#ifndef __MCF523X_H__
#define __MCF523X_H__
/*********************************************************************/
#include "mcf523x/mcf523x_fec.h"
#include "mcf523x/mcf523x_rng.h"
#include "mcf523x/mcf523x_fmpll.h"
#include "mcf523x/mcf523x_cs.h"
#include "mcf523x/mcf523x_intc0.h"
#include "mcf523x/mcf523x_intc1.h"
#include "mcf523x/mcf523x_sdramc.h"
#include "mcf523x/mcf523x_sram.h"
#include "mcf523x/mcf523x_uart.h"
#include "mcf523x/mcf523x_timer.h"
#include "mcf523x/mcf523x_qspi.h"
#include "mcf523x/mcf523x_eport.h"
#include "mcf523x/mcf523x_i2c.h"
#include "mcf523x/mcf523x_scm.h"
#include "mcf523x/mcf523x_pit.h"
#include "mcf523x/mcf523x_can.h"
#include "mcf523x/mcf523x_wtm.h"
#include "mcf523x/mcf523x_gpio.h"
#include "mcf523x/mcf523x_mdha.h"
#include "mcf523x/mcf523x_ccm.h"
#include "mcf523x/mcf523x_rcm.h"
#include "mcf523x/mcf523x_etpu.h"
/********************************************************************/
#endif /* __MCF523X_H__ */

View File

@@ -0,0 +1,319 @@
/*
* File: mcf523x_can.h
* Purpose: Register and bit definitions for the MCF523X
*
* Notes:
*
*/
#ifndef __MCF523X_CAN_H__
#define __MCF523X_CAN_H__
/*********************************************************************
*
* FlexCAN Module (CAN)
*
*********************************************************************/
/* Register read/write macros */
#define MCF_CAN_CANMCR0 (*(vuint32*)(void*)(&__IPSBAR[0x1C0000]))
#define MCF_CAN_CANCTRL0 (*(vuint32*)(void*)(&__IPSBAR[0x1C0004]))
#define MCF_CAN_TIMER0 (*(vuint32*)(void*)(&__IPSBAR[0x1C0008]))
#define MCF_CAN_RXGMASK0 (*(vuint32*)(void*)(&__IPSBAR[0x1C0010]))
#define MCF_CAN_RX14MASK0 (*(vuint32*)(void*)(&__IPSBAR[0x1C0014]))
#define MCF_CAN_RX15MASK0 (*(vuint32*)(void*)(&__IPSBAR[0x1C0018]))
#define MCF_CAN_ERRCNT0 (*(vuint32*)(void*)(&__IPSBAR[0x1C001C]))
#define MCF_CAN_ERRSTAT0 (*(vuint32*)(void*)(&__IPSBAR[0x1C0020]))
#define MCF_CAN_IMASK0 (*(vuint16*)(void*)(&__IPSBAR[0x1C002A]))
#define MCF_CAN_IFLAG0 (*(vuint16*)(void*)(&__IPSBAR[0x1C0032]))
#define MCF_CAN_CANMCR1 (*(vuint32*)(void*)(&__IPSBAR[0x1F0000]))
#define MCF_CAN_CANCTRL1 (*(vuint32*)(void*)(&__IPSBAR[0x1F0004]))
#define MCF_CAN_TIMER1 (*(vuint32*)(void*)(&__IPSBAR[0x1F0008]))
#define MCF_CAN_RXGMASK1 (*(vuint32*)(void*)(&__IPSBAR[0x1F0010]))
#define MCF_CAN_RX14MASK1 (*(vuint32*)(void*)(&__IPSBAR[0x1F0014]))
#define MCF_CAN_RX15MASK1 (*(vuint32*)(void*)(&__IPSBAR[0x1F0018]))
#define MCF_CAN_ERRCNT1 (*(vuint32*)(void*)(&__IPSBAR[0x1F001C]))
#define MCF_CAN_ERRSTAT1 (*(vuint32*)(void*)(&__IPSBAR[0x1F0020]))
#define MCF_CAN_IMASK1 (*(vuint16*)(void*)(&__IPSBAR[0x1F002A]))
#define MCF_CAN_IFLAG1 (*(vuint16*)(void*)(&__IPSBAR[0x1F0032]))
#define MCF_CAN_CANMCR(x) (*(vuint32*)(void*)(&__IPSBAR[0x1C0000+((x)*0x30000)]))
#define MCF_CAN_CANCTRL(x) (*(vuint32*)(void*)(&__IPSBAR[0x1C0004+((x)*0x30000)]))
#define MCF_CAN_TIMER(x) (*(vuint32*)(void*)(&__IPSBAR[0x1C0008+((x)*0x30000)]))
#define MCF_CAN_RXGMASK(x) (*(vuint32*)(void*)(&__IPSBAR[0x1C0010+((x)*0x30000)]))
#define MCF_CAN_RX14MASK(x) (*(vuint32*)(void*)(&__IPSBAR[0x1C0014+((x)*0x30000)]))
#define MCF_CAN_RX15MASK(x) (*(vuint32*)(void*)(&__IPSBAR[0x1C0018+((x)*0x30000)]))
#define MCF_CAN_ERRCNT(x) (*(vuint32*)(void*)(&__IPSBAR[0x1C001C+((x)*0x30000)]))
#define MCF_CAN_ERRSTAT(x) (*(vuint32*)(void*)(&__IPSBAR[0x1C0020+((x)*0x30000)]))
#define MCF_CAN_IMASK(x) (*(vuint16*)(void*)(&__IPSBAR[0x1C002A+((x)*0x30000)]))
#define MCF_CAN_IFLAG(x) (*(vuint16*)(void*)(&__IPSBAR[0x1C0032+((x)*0x30000)]))
#define MCF_CAN_MBUF0_CTRL(x) (*(vuint16 *)(void *)(&__IPSBAR[0x1C0080+((x)*0x30000)]))
#define MCF_CAN_MBUF0_TMSTP(x) (*(vuint16 *)(void *)(&__IPSBAR[0x1C0082+((x)*0x30000)]))
#define MCF_CAN_MBUF0_ID(x) (*(vuint32 *)(void *)(&__IPSBAR[0x1C0084+((x)*0x30000)]))
#define MCF_CAN_MBUF0_BYTE0(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C0088+((x)*0x30000)]))
#define MCF_CAN_MBUF0_BYTE1(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C0089+((x)*0x30000)]))
#define MCF_CAN_MBUF0_BYTE2(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C008A+((x)*0x30000)]))
#define MCF_CAN_MBUF0_BYTE3(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C008B+((x)*0x30000)]))
#define MCF_CAN_MBUF0_BYTE4(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C008C+((x)*0x30000)]))
#define MCF_CAN_MBUF0_BYTE5(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C008D+((x)*0x30000)]))
#define MCF_CAN_MBUF0_BYTE6(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C008E+((x)*0x30000)]))
#define MCF_CAN_MBUF0_BYTE7(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C008F+((x)*0x30000)]))
#define MCF_CAN_MBUF1_CTRL(x) (*(vuint16 *)(void *)(&__IPSBAR[0x1C0090+((x)*0x30000)]))
#define MCF_CAN_MBUF1_TMSTP(x) (*(vuint16 *)(void *)(&__IPSBAR[0x1C0092+((x)*0x30000)]))
#define MCF_CAN_MBUF1_ID(x) (*(vuint32 *)(void *)(&__IPSBAR[0x1C0094+((x)*0x30000)]))
#define MCF_CAN_MBUF1_BYTE0(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C0098+((x)*0x30000)]))
#define MCF_CAN_MBUF1_BYTE1(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C0099+((x)*0x30000)]))
#define MCF_CAN_MBUF1_BYTE2(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C009A+((x)*0x30000)]))
#define MCF_CAN_MBUF1_BYTE3(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C009B+((x)*0x30000)]))
#define MCF_CAN_MBUF1_BYTE4(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C009C+((x)*0x30000)]))
#define MCF_CAN_MBUF1_BYTE5(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C009D+((x)*0x30000)]))
#define MCF_CAN_MBUF1_BYTE6(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C009E+((x)*0x30000)]))
#define MCF_CAN_MBUF1_BYTE7(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C009F+((x)*0x30000)]))
#define MCF_CAN_MBUF2_CTRL(x) (*(vuint16 *)(void *)(&__IPSBAR[0x1C00A0+((x)*0x30000)]))
#define MCF_CAN_MBUF2_ID(x) (*(vuint32 *)(void *)(&__IPSBAR[0x1C00A4+((x)*0x30000)]))
#define MCF_CAN_MBUF2_BYTE0(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00A8+((x)*0x30000)]))
#define MCF_CAN_MBUF2_BYTE1(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00A9+((x)*0x30000)]))
#define MCF_CAN_MBUF2_BYTE2(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00AA+((x)*0x30000)]))
#define MCF_CAN_MBUF2_BYTE3(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00AB+((x)*0x30000)]))
#define MCF_CAN_MBUF2_BYTE4(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00AC+((x)*0x30000)]))
#define MCF_CAN_MBUF2_BYTE5(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00AD+((x)*0x30000)]))
#define MCF_CAN_MBUF2_BYTE6(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00AE+((x)*0x30000)]))
#define MCF_CAN_MBUF2_BYTE7(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00AF+((x)*0x30000)]))
#define MCF_CAN_MBUF3_CTRL(x) (*(vuint16 *)(void *)(&__IPSBAR[0x1C00B0+((x)*0x30000)]))
#define MCF_CAN_MBUF3_ID(x) (*(vuint32 *)(void *)(&__IPSBAR[0x1C00B4+((x)*0x30000)]))
#define MCF_CAN_MBUF3_BYTE0(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00B8+((x)*0x30000)]))
#define MCF_CAN_MBUF3_BYTE1(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00B9+((x)*0x30000)]))
#define MCF_CAN_MBUF3_BYTE2(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00BA+((x)*0x30000)]))
#define MCF_CAN_MBUF3_BYTE3(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00BB+((x)*0x30000)]))
#define MCF_CAN_MBUF3_BYTE4(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00BC+((x)*0x30000)]))
#define MCF_CAN_MBUF3_BYTE5(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00BD+((x)*0x30000)]))
#define MCF_CAN_MBUF3_BYTE6(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00BE+((x)*0x30000)]))
#define MCF_CAN_MBUF3_BYTE7(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00BF+((x)*0x30000)]))
#define MCF_CAN_MBUF4_CTRL(x) (*(vuint16 *)(void *)(&__IPSBAR[0x1C00C0+((x)*0x30000)]))
#define MCF_CAN_MBUF4_ID(x) (*(vuint32 *)(void *)(&__IPSBAR[0x1C00C4+((x)*0x30000)]))
#define MCF_CAN_MBUF4_BYTE0(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00C8+((x)*0x30000)]))
#define MCF_CAN_MBUF4_BYTE1(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00C9+((x)*0x30000)]))
#define MCF_CAN_MBUF4_BYTE2(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00CA+((x)*0x30000)]))
#define MCF_CAN_MBUF4_BYTE3(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00CB+((x)*0x30000)]))
#define MCF_CAN_MBUF4_BYTE4(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00CC+((x)*0x30000)]))
#define MCF_CAN_MBUF4_BYTE5(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00CD+((x)*0x30000)]))
#define MCF_CAN_MBUF4_BYTE6(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00CE+((x)*0x30000)]))
#define MCF_CAN_MBUF4_BYTE7(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00CF+((x)*0x30000)]))
#define MCF_CAN_MBUF5_CTRL(x) (*(vuint16 *)(void *)(&__IPSBAR[0x1C00D0+((x)*0x30000)]))
#define MCF_CAN_MBUF5_ID(x) (*(vuint32 *)(void *)(&__IPSBAR[0x1C00D4+((x)*0x30000)]))
#define MCF_CAN_MBUF5_BYTE0(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00D8+((x)*0x30000)]))
#define MCF_CAN_MBUF5_BYTE1(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00D9+((x)*0x30000)]))
#define MCF_CAN_MBUF5_BYTE2(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00DA+((x)*0x30000)]))
#define MCF_CAN_MBUF5_BYTE3(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00DB+((x)*0x30000)]))
#define MCF_CAN_MBUF5_BYTE4(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00DC+((x)*0x30000)]))
#define MCF_CAN_MBUF5_BYTE5(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00DD+((x)*0x30000)]))
#define MCF_CAN_MBUF5_BYTE6(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00DE+((x)*0x30000)]))
#define MCF_CAN_MBUF5_BYTE7(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00DF+((x)*0x30000)]))
#define MCF_CAN_MBUF6_CTRL(x) (*(vuint16 *)(void *)(&__IPSBAR[0x1C00E0+((x)*0x30000)]))
#define MCF_CAN_MBUF6_ID(x) (*(vuint32 *)(void *)(&__IPSBAR[0x1C00E4+((x)*0x30000)]))
#define MCF_CAN_MBUF6_BYTE0(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00E8+((x)*0x30000)]))
#define MCF_CAN_MBUF6_BYTE1(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00E9+((x)*0x30000)]))
#define MCF_CAN_MBUF6_BYTE2(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00EA+((x)*0x30000)]))
#define MCF_CAN_MBUF6_BYTE3(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00EB+((x)*0x30000)]))
#define MCF_CAN_MBUF6_BYTE4(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00EC+((x)*0x30000)]))
#define MCF_CAN_MBUF6_BYTE5(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00ED+((x)*0x30000)]))
#define MCF_CAN_MBUF6_BYTE6(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00EE+((x)*0x30000)]))
#define MCF_CAN_MBUF6_BYTE7(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00EF+((x)*0x30000)]))
#define MCF_CAN_MBUF7_CTRL(x) (*(vuint16 *)(void *)(&__IPSBAR[0x1C00F0+((x)*0x30000)]))
#define MCF_CAN_MBUF7_ID(x) (*(vuint32 *)(void *)(&__IPSBAR[0x1C00F4+((x)*0x30000)]))
#define MCF_CAN_MBUF7_BYTE0(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00F8+((x)*0x30000)]))
#define MCF_CAN_MBUF7_BYTE1(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00F9+((x)*0x30000)]))
#define MCF_CAN_MBUF7_BYTE2(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00FA+((x)*0x30000)]))
#define MCF_CAN_MBUF7_BYTE3(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00FB+((x)*0x30000)]))
#define MCF_CAN_MBUF7_BYTE4(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00FC+((x)*0x30000)]))
#define MCF_CAN_MBUF7_BYTE5(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00FD+((x)*0x30000)]))
#define MCF_CAN_MBUF7_BYTE6(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00FE+((x)*0x30000)]))
#define MCF_CAN_MBUF7_BYTE7(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C00FF+((x)*0x30000)]))
#define MCF_CAN_MBUF8_CTRL(x) (*(vuint16 *)(void *)(&__IPSBAR[0x1C0100+((x)*0x30000)]))
#define MCF_CAN_MBUF8_ID(x) (*(vuint32 *)(void *)(&__IPSBAR[0x1C0104+((x)*0x30000)]))
#define MCF_CAN_MBUF8_BYTE0(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C0108+((x)*0x30000)]))
#define MCF_CAN_MBUF8_BYTE1(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C0109+((x)*0x30000)]))
#define MCF_CAN_MBUF8_BYTE2(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C010A+((x)*0x30000)]))
#define MCF_CAN_MBUF8_BYTE3(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C010B+((x)*0x30000)]))
#define MCF_CAN_MBUF8_BYTE4(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C010C+((x)*0x30000)]))
#define MCF_CAN_MBUF8_BYTE5(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C010D+((x)*0x30000)]))
#define MCF_CAN_MBUF8_BYTE6(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C010E+((x)*0x30000)]))
#define MCF_CAN_MBUF8_BYTE7(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C010F+((x)*0x30000)]))
#define MCF_CAN_MBUF9_CTRL(x) (*(vuint16 *)(void *)(&__IPSBAR[0x1C0100+((x)*0x30000)]))
#define MCF_CAN_MBUF9_ID(x) (*(vuint32 *)(void *)(&__IPSBAR[0x1C0114+((x)*0x30000)]))
#define MCF_CAN_MBUF9_BYTE0(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C0118+((x)*0x30000)]))
#define MCF_CAN_MBUF9_BYTE1(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C0119+((x)*0x30000)]))
#define MCF_CAN_MBUF9_BYTE2(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C011A+((x)*0x30000)]))
#define MCF_CAN_MBUF9_BYTE3(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C011B+((x)*0x30000)]))
#define MCF_CAN_MBUF9_BYTE4(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C011C+((x)*0x30000)]))
#define MCF_CAN_MBUF9_BYTE5(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C011D+((x)*0x30000)]))
#define MCF_CAN_MBUF9_BYTE6(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C011E+((x)*0x30000)]))
#define MCF_CAN_MBUF9_BYTE7(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C011F+((x)*0x30000)]))
#define MCF_CAN_MBUF10_CTRL(x) (*(vuint16 *)(void *)(&__IPSBAR[0x1C0120+((x)*0x30000)]))
#define MCF_CAN_MBUF10_ID(x) (*(vuint32 *)(void *)(&__IPSBAR[0x1C0124+((x)*0x30000)]))
#define MCF_CAN_MBUF10_BYTE0(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C0128+((x)*0x30000)]))
#define MCF_CAN_MBUF10_BYTE1(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C0129+((x)*0x30000)]))
#define MCF_CAN_MBUF10_BYTE2(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C012A+((x)*0x30000)]))
#define MCF_CAN_MBUF10_BYTE3(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C012B+((x)*0x30000)]))
#define MCF_CAN_MBUF10_BYTE4(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C012C+((x)*0x30000)]))
#define MCF_CAN_MBUF10_BYTE5(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C012D+((x)*0x30000)]))
#define MCF_CAN_MBUF10_BYTE6(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C012E+((x)*0x30000)]))
#define MCF_CAN_MBUF10_BYTE7(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C012F+((x)*0x30000)]))
#define MCF_CAN_MBUF11_CTRL(x) (*(vuint16 *)(void *)(&__IPSBAR[0x1C0130+((x)*0x30000)]))
#define MCF_CAN_MBUF11_ID(x) (*(vuint32 *)(void *)(&__IPSBAR[0x1C0134+((x)*0x30000)]))
#define MCF_CAN_MBUF11_BYTE0(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C0138+((x)*0x30000)]))
#define MCF_CAN_MBUF11_BYTE1(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C0139+((x)*0x30000)]))
#define MCF_CAN_MBUF11_BYTE2(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C013A+((x)*0x30000)]))
#define MCF_CAN_MBUF11_BYTE3(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C013B+((x)*0x30000)]))
#define MCF_CAN_MBUF11_BYTE4(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C013C+((x)*0x30000)]))
#define MCF_CAN_MBUF11_BYTE5(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C013D+((x)*0x30000)]))
#define MCF_CAN_MBUF11_BYTE6(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C013E+((x)*0x30000)]))
#define MCF_CAN_MBUF11_BYTE7(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C013F+((x)*0x30000)]))
#define MCF_CAN_MBUF12_CTRL(x) (*(vuint16 *)(void *)(&__IPSBAR[0x1C0140+((x)*0x30000)]))
#define MCF_CAN_MBUF12_ID(x) (*(vuint32 *)(void *)(&__IPSBAR[0x1C0144+((x)*0x30000)]))
#define MCF_CAN_MBUF12_BYTE0(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C0148+((x)*0x30000)]))
#define MCF_CAN_MBUF12_BYTE1(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C0149+((x)*0x30000)]))
#define MCF_CAN_MBUF12_BYTE2(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C014A+((x)*0x30000)]))
#define MCF_CAN_MBUF12_BYTE3(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C014B+((x)*0x30000)]))
#define MCF_CAN_MBUF12_BYTE4(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C014C+((x)*0x30000)]))
#define MCF_CAN_MBUF12_BYTE5(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C014D+((x)*0x30000)]))
#define MCF_CAN_MBUF12_BYTE6(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C014E+((x)*0x30000)]))
#define MCF_CAN_MBUF12_BYTE7(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C014F+((x)*0x30000)]))
#define MCF_CAN_MBUF13_CTRL(x) (*(vuint16 *)(void *)(&__IPSBAR[0x1C0150+((x)*0x30000)]))
#define MCF_CAN_MBUF13_ID(x) (*(vuint32 *)(void *)(&__IPSBAR[0x1C0154+((x)*0x30000)]))
#define MCF_CAN_MBUF13_BYTE0(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C0158+((x)*0x30000)]))
#define MCF_CAN_MBUF13_BYTE1(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C0159+((x)*0x30000)]))
#define MCF_CAN_MBUF13_BYTE2(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C015A+((x)*0x30000)]))
#define MCF_CAN_MBUF13_BYTE3(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C015B+((x)*0x30000)]))
#define MCF_CAN_MBUF13_BYTE4(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C015C+((x)*0x30000)]))
#define MCF_CAN_MBUF13_BYTE5(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C015D+((x)*0x30000)]))
#define MCF_CAN_MBUF13_BYTE6(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C015E+((x)*0x30000)]))
#define MCF_CAN_MBUF13_BYTE7(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C015F+((x)*0x30000)]))
#define MCF_CAN_MBUF14_CTRL(x) (*(vuint16 *)(void *)(&__IPSBAR[0x1C0160+((x)*0x30000)]))
#define MCF_CAN_MBUF14_ID(x) (*(vuint32 *)(void *)(&__IPSBAR[0x1C0164+((x)*0x30000)]))
#define MCF_CAN_MBUF14_BYTE0(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C0168+((x)*0x30000)]))
#define MCF_CAN_MBUF14_BYTE1(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C0169+((x)*0x30000)]))
#define MCF_CAN_MBUF14_BYTE2(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C016A+((x)*0x30000)]))
#define MCF_CAN_MBUF14_BYTE3(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C016B+((x)*0x30000)]))
#define MCF_CAN_MBUF14_BYTE4(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C016C+((x)*0x30000)]))
#define MCF_CAN_MBUF14_BYTE5(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C016D+((x)*0x30000)]))
#define MCF_CAN_MBUF14_BYTE6(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C016E+((x)*0x30000)]))
#define MCF_CAN_MBUF14_BYTE7(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C016F+((x)*0x30000)]))
#define MCF_CAN_MBUF15_CTRL(x) (*(vuint16 *)(void *)(&__IPSBAR[0x1C0170+((x)*0x30000)]))
#define MCF_CAN_MBUF15_ID(x) (*(vuint32 *)(void *)(&__IPSBAR[0x1C0174+((x)*0x30000)]))
#define MCF_CAN_MBUF15_BYTE0(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C0178+((x)*0x30000)]))
#define MCF_CAN_MBUF15_BYTE1(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C0179+((x)*0x30000)]))
#define MCF_CAN_MBUF15_BYTE2(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C017A+((x)*0x30000)]))
#define MCF_CAN_MBUF15_BYTE3(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C017B+((x)*0x30000)]))
#define MCF_CAN_MBUF15_BYTE4(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C017C+((x)*0x30000)]))
#define MCF_CAN_MBUF15_BYTE5(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C017D+((x)*0x30000)]))
#define MCF_CAN_MBUF15_BYTE6(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C017E+((x)*0x30000)]))
#define MCF_CAN_MBUF15_BYTE7(x) (*(vuint8 *)(void *)(&__IPSBAR[0x1C017F+((x)*0x30000)]))
#define MCF_CAN_MBUF0_DATAL(x) (*(vuint32 *)(void *)(&__IPSBAR[0x1C0088+((x)*0x30000)]))
#define MCF_CAN_MBUF0_DATAH(x) (*(vuint32 *)(void *)(&__IPSBAR[0x1C008C+((x)*0x30000)]))
#define MCF_CAN_MBUF1_DATAL(x) (*(vuint32 *)(void *)(&__IPSBAR[0x1C0098+((x)*0x30000)]))
#define MCF_CAN_MBUF1_DATAH(x) (*(vuint32 *)(void *)(&__IPSBAR[0x1C009C+((x)*0x30000)]))
#define MCF_CAN_MBUF2_DATAL(x) (*(vuint32 *)(void *)(&__IPSBAR[0x1C00A8+((x)*0x30000)]))
#define MCF_CAN_MBUF2_DATAH(x) (*(vuint32 *)(void *)(&__IPSBAR[0x1C00AC+((x)*0x30000)]))
/* Bit definitions and macros for MCF_CAN_CANMCR */
#define MCF_CAN_CANMCR_MAXMB(x) (((x)&0x0000000F)<<0)
#define MCF_CAN_CANMCR_SUPV (0x00800000)
#define MCF_CAN_CANMCR_FRZACK (0x01000000)
#define MCF_CAN_CANMCR_SOFTRST (0x02000000)
#define MCF_CAN_CANMCR_HALT (0x10000000)
#define MCF_CAN_CANMCR_FRZ (0x40000000)
#define MCF_CAN_CANMCR_MDIS (0x80000000)
/* Bit definitions and macros for MCF_CAN_CANCTRL */
#define MCF_CAN_CANCTRL_PROPSEG(x) (((x)&0x00000007)<<0)
#define MCF_CAN_CANCTRL_LOM (0x00000008)
#define MCF_CAN_CANCTRL_LBUF (0x00000010)
#define MCF_CAN_CANCTRL_TSYNC (0x00000020)
#define MCF_CAN_CANCTRL_BOFFREC (0x00000040)
#define MCF_CAN_CANCTRL_SAMP (0x00000080)
#define MCF_CAN_CANCTRL_LPB (0x00001000)
#define MCF_CAN_CANCTRL_CLKSRC (0x00002000)
#define MCF_CAN_CANCTRL_ERRMSK (0x00004000)
#define MCF_CAN_CANCTRL_BOFFMSK (0x00008000)
#define MCF_CAN_CANCTRL_PSEG2(x) (((x)&0x00000007)<<16)
#define MCF_CAN_CANCTRL_PSEG1(x) (((x)&0x00000007)<<19)
#define MCF_CAN_CANCTRL_RJW(x) (((x)&0x00000003)<<22)
#define MCF_CAN_CANCTRL_PRESDIV(x) (((x)&0x000000FF)<<24)
/* Bit definitions and macros for MCF_CAN_TIMER */
#define MCF_CAN_TIMER_TIMER(x) (((x)&0x0000FFFF)<<0)
/* Bit definitions and macros for MCF_CAN_RXGMASK */
#define MCF_CAN_RXGMASK_MI(x) (((x)&0x1FFFFFFF)<<0)
/* Bit definitions and macros for MCF_CAN_RX14MASK */
#define MCF_CAN_RX14MASK_MI(x) (((x)&0x1FFFFFFF)<<0)
/* Bit definitions and macros for MCF_CAN_RX15MASK */
#define MCF_CAN_RX15MASK_MI(x) (((x)&0x1FFFFFFF)<<0)
/* Bit definitions and macros for MCF_CAN_ERRCNT */
#define MCF_CAN_ERRCNT_TXECTR(x) (((x)&0x000000FF)<<0)
#define MCF_CAN_ERRCNT_RXECTR(x) (((x)&0x000000FF)<<8)
/* Bit definitions and macros for MCF_CAN_ERRSTAT */
#define MCF_CAN_ERRSTAT_WAKINT (0x00000001)
#define MCF_CAN_ERRSTAT_ERRINT (0x00000002)
#define MCF_CAN_ERRSTAT_BOFFINT (0x00000004)
#define MCF_CAN_ERRSTAT_FLTCONF(x) (((x)&0x00000003)<<4)
#define MCF_CAN_ERRSTAT_TXRX (0x00000040)
#define MCF_CAN_ERRSTAT_IDLE (0x00000080)
#define MCF_CAN_ERRSTAT_RXWRN (0x00000100)
#define MCF_CAN_ERRSTAT_TXWRN (0x00000200)
#define MCF_CAN_ERRSTAT_STFERR (0x00000400)
#define MCF_CAN_ERRSTAT_FRMERR (0x00000800)
#define MCF_CAN_ERRSTAT_CRCERR (0x00001000)
#define MCF_CAN_ERRSTAT_ACKERR (0x00002000)
#define MCF_CAN_ERRSTAT_BITERR(x) (((x)&0x00000003)<<14)
#define MCF_CAN_ERRSTAT_FLTCONF_ACTIVE (0x00000000)
#define MCF_CAN_ERRSTAT_FLTCONF_PASSIVE (0x00000010)
#define MCF_CAN_ERRSTAT_FLTCONF_BUSOFF (0x00000020)
/* Bit definitions and macros for MCF_CAN_IMASK */
#define MCF_CAN_IMASK_BUF0M (0x0001)
#define MCF_CAN_IMASK_BUF1M (0x0002)
#define MCF_CAN_IMASK_BUF2M (0x0004)
#define MCF_CAN_IMASK_BUF3M (0x0008)
#define MCF_CAN_IMASK_BUF4M (0x0010)
#define MCF_CAN_IMASK_BUF5M (0x0020)
#define MCF_CAN_IMASK_BUF6M (0x0040)
#define MCF_CAN_IMASK_BUF7M (0x0080)
#define MCF_CAN_IMASK_BUF8M (0x0100)
#define MCF_CAN_IMASK_BUF9M (0x0200)
#define MCF_CAN_IMASK_BUF10M (0x0400)
#define MCF_CAN_IMASK_BUF11M (0x0800)
#define MCF_CAN_IMASK_BUF12M (0x1000)
#define MCF_CAN_IMASK_BUF13M (0x2000)
#define MCF_CAN_IMASK_BUF14M (0x4000)
#define MCF_CAN_IMASK_BUF15M (0x8000)
/* Bit definitions and macros for MCF_CAN_IFLAG */
#define MCF_CAN_IFLAG_BUF0I (0x0001)
#define MCF_CAN_IFLAG_BUF1I (0x0002)
#define MCF_CAN_IFLAG_BUF2I (0x0004)
#define MCF_CAN_IFLAG_BUF3I (0x0008)
#define MCF_CAN_IFLAG_BUF4I (0x0010)
#define MCF_CAN_IFLAG_BUF5I (0x0020)
#define MCF_CAN_IFLAG_BUF6I (0x0040)
#define MCF_CAN_IFLAG_BUF7I (0x0080)
#define MCF_CAN_IFLAG_BUF8I (0x0100)
#define MCF_CAN_IFLAG_BUF9I (0x0200)
#define MCF_CAN_IFLAG_BUF10I (0x0400)
#define MCF_CAN_IFLAG_BUF11I (0x0800)
#define MCF_CAN_IFLAG_BUF12I (0x1000)
#define MCF_CAN_IFLAG_BUF13I (0x2000)
#define MCF_CAN_IFLAG_BUF14I (0x4000)
#define MCF_CAN_IFLAG_BUF15I (0x8000)
/********************************************************************/
#endif /* __MCF523X_CAN_H__ */

View File

@@ -0,0 +1,50 @@
/*
* File: mcf523x_ccm.h
* Purpose: Register and bit definitions for the MCF523X
*
* Notes:
*
*/
#ifndef __MCF523X_CCM_H__
#define __MCF523X_CCM_H__
/*********************************************************************
*
* Chip Configuration Module (CCM)
*
*********************************************************************/
/* Register read/write macros */
#define MCF_CCM_CCR (*(vuint16*)(void*)(&__IPSBAR[0x110004]))
#define MCF_CCM_LPCR (*(vuint8 *)(void*)(&__IPSBAR[0x110007]))
#define MCF_CCM_CIR (*(vuint16*)(void*)(&__IPSBAR[0x11000A]))
#define MCF_CCM_RCON (*(vuint16*)(void*)(&__IPSBAR[0x110008]))
/* Bit definitions and macros for MCF_CCM_CCR */
#define MCF_CCM_CCR_BMT(x) (((x)&0x0007)<<0)
#define MCF_CCM_CCR_BME (0x0008)
#define MCF_CCM_CCR_SZEN (0x0040)
#define MCF_CCM_CCR_MODE(x) (((x)&0x0007)<<8)
/* Bit definitions and macros for MCF_CCM_LPCR */
#define MCF_CCM_LPCR_STPMD(x) (((x)&0x03)<<3)
#define MCF_CCM_LPCR_LPMD(x) (((x)&0x03)<<6)
#define MCF_CCM_LPCR_LPMD_STOP (0xC0)
#define MCF_CCM_LPCR_LPMD_WAIT (0x80)
#define MCF_CCM_LPCR_LPMD_DOZE (0x40)
#define MCF_CCM_LPCR_LPMD_RUN (0x00)
/* Bit definitions and macros for MCF_CCM_CIR */
#define MCF_CCM_CIR_PRN(x) (((x)&0x003F)<<0)
#define MCF_CCM_CIR_PIN(x) (((x)&0x03FF)<<6)
/* Bit definitions and macros for MCF_CCM_RCON */
#define MCF_CCM_RCON_MODE (0x0001)
#define MCF_CCM_RCON_BOOTPS(x) (((x)&0x0003)<<3)
#define MCF_CCM_RCON_RLOAD (0x0020)
#define MCF_CCM_RCON_RCSC(x) (((x)&0x0003)<<8)
/********************************************************************/
#endif /* __MCF523X_CCM_H__ */

View File

@@ -0,0 +1,95 @@
/*
* File: mcf523x_cs.h
* Purpose: Register and bit definitions for the MCF523X
*
* Notes:
*
*/
#ifndef __MCF523X_CS_H__
#define __MCF523X_CS_H__
/*********************************************************************
*
* Chip Selects (CS)
*
*********************************************************************/
/* Register read/write macros */
#define MCF_CS_CSAR0 (*(vuint16*)(void*)(&__IPSBAR[0x000080]))
#define MCF_CS_CSMR0 (*(vuint32*)(void*)(&__IPSBAR[0x000084]))
#define MCF_CS_CSCR0 (*(vuint16*)(void*)(&__IPSBAR[0x00008A]))
#define MCF_CS_CSAR1 (*(vuint16*)(void*)(&__IPSBAR[0x00008C]))
#define MCF_CS_CSMR1 (*(vuint32*)(void*)(&__IPSBAR[0x000090]))
#define MCF_CS_CSCR1 (*(vuint16*)(void*)(&__IPSBAR[0x000096]))
#define MCF_CS_CSAR2 (*(vuint16*)(void*)(&__IPSBAR[0x000098]))
#define MCF_CS_CSMR2 (*(vuint32*)(void*)(&__IPSBAR[0x00009C]))
#define MCF_CS_CSCR2 (*(vuint16*)(void*)(&__IPSBAR[0x0000A2]))
#define MCF_CS_CSAR3 (*(vuint16*)(void*)(&__IPSBAR[0x0000A4]))
#define MCF_CS_CSMR3 (*(vuint32*)(void*)(&__IPSBAR[0x0000A8]))
#define MCF_CS_CSCR3 (*(vuint16*)(void*)(&__IPSBAR[0x0000AE]))
#define MCF_CS_CSAR4 (*(vuint16*)(void*)(&__IPSBAR[0x0000B0]))
#define MCF_CS_CSMR4 (*(vuint32*)(void*)(&__IPSBAR[0x0000B4]))
#define MCF_CS_CSCR4 (*(vuint16*)(void*)(&__IPSBAR[0x0000BA]))
#define MCF_CS_CSAR5 (*(vuint16*)(void*)(&__IPSBAR[0x0000BC]))
#define MCF_CS_CSMR5 (*(vuint32*)(void*)(&__IPSBAR[0x0000C0]))
#define MCF_CS_CSCR5 (*(vuint16*)(void*)(&__IPSBAR[0x0000C6]))
#define MCF_CS_CSAR6 (*(vuint16*)(void*)(&__IPSBAR[0x0000C8]))
#define MCF_CS_CSMR6 (*(vuint32*)(void*)(&__IPSBAR[0x0000CC]))
#define MCF_CS_CSCR6 (*(vuint16*)(void*)(&__IPSBAR[0x0000D2]))
#define MCF_CS_CSAR7 (*(vuint16*)(void*)(&__IPSBAR[0x0000D4]))
#define MCF_CS_CSMR7 (*(vuint32*)(void*)(&__IPSBAR[0x0000D8]))
#define MCF_CS_CSCR7 (*(vuint16*)(void*)(&__IPSBAR[0x0000DE]))
#define MCF_CS_CSAR(x) (*(vuint16*)(void*)(&__IPSBAR[0x000080+((x)*0x00C)]))
#define MCF_CS_CSMR(x) (*(vuint32*)(void*)(&__IPSBAR[0x000084+((x)*0x00C)]))
#define MCF_CS_CSCR(x) (*(vuint16*)(void*)(&__IPSBAR[0x00008A+((x)*0x00C)]))
/* Bit definitions and macros for MCF_CS_CSAR */
#define MCF_CS_CSAR_BA(x) ((uint16)(((x)&0xFFFF0000)>>16))
/* Bit definitions and macros for MCF_CS_CSMR */
#define MCF_CS_CSMR_V (0x00000001)
#define MCF_CS_CSMR_UD (0x00000002)
#define MCF_CS_CSMR_UC (0x00000004)
#define MCF_CS_CSMR_SD (0x00000008)
#define MCF_CS_CSMR_SC (0x00000010)
#define MCF_CS_CSMR_CI (0x00000020)
#define MCF_CS_CSMR_AM (0x00000040)
#define MCF_CS_CSMR_WP (0x00000100)
#define MCF_CS_CSMR_BAM(x) (((x)&0x0000FFFF)<<16)
#define MCF_CS_CSMR_BAM_4G (0xFFFF0000)
#define MCF_CS_CSMR_BAM_2G (0x7FFF0000)
#define MCF_CS_CSMR_BAM_1G (0x3FFF0000)
#define MCF_CS_CSMR_BAM_1024M (0x3FFF0000)
#define MCF_CS_CSMR_BAM_512M (0x1FFF0000)
#define MCF_CS_CSMR_BAM_256M (0x0FFF0000)
#define MCF_CS_CSMR_BAM_128M (0x07FF0000)
#define MCF_CS_CSMR_BAM_64M (0x03FF0000)
#define MCF_CS_CSMR_BAM_32M (0x01FF0000)
#define MCF_CS_CSMR_BAM_16M (0x00FF0000)
#define MCF_CS_CSMR_BAM_8M (0x007F0000)
#define MCF_CS_CSMR_BAM_4M (0x003F0000)
#define MCF_CS_CSMR_BAM_2M (0x001F0000)
#define MCF_CS_CSMR_BAM_1M (0x000F0000)
#define MCF_CS_CSMR_BAM_1024K (0x000F0000)
#define MCF_CS_CSMR_BAM_512K (0x00070000)
#define MCF_CS_CSMR_BAM_256K (0x00030000)
#define MCF_CS_CSMR_BAM_128K (0x00010000)
#define MCF_CS_CSMR_BAM_64K (0x00000000)
/* Bit definitions and macros for MCF_CS_CSCR */
#define MCF_CS_CSCR_SWWS(x) (((x)&0x0007)<<0)
#define MCF_CS_CSCR_BSTW (0x0008)
#define MCF_CS_CSCR_BSTR (0x0010)
#define MCF_CS_CSCR_BEM (0x0020)
#define MCF_CS_CSCR_PS(x) (((x)&0x0003)<<6)
#define MCF_CS_CSCR_AA (0x0100)
#define MCF_CS_CSCR_IWS(x) (((x)&0x000F)<<10)
#define MCF_CS_CSCR_SRWS(x) (((x)&0x0003)<<14)
#define MCF_CS_CSCR_PS_8 (0x0040)
#define MCF_CS_CSCR_PS_16 (0x0080)
#define MCF_CS_CSCR_PS_32 (0x0000)
/********************************************************************/
#endif /* __MCF523X_CS_H__ */

View File

@@ -0,0 +1,86 @@
/*
* File: mcf523x_eport.h
* Purpose: Register and bit definitions for the MCF523X
*
* Notes:
*
*/
#ifndef __MCF523X_EPORT_H__
#define __MCF523X_EPORT_H__
/*********************************************************************
*
* Edge Port Module (EPORT)
*
*********************************************************************/
/* Register read/write macros */
#define MCF_EPORT_EPPAR (*(vuint16*)(void*)(&__IPSBAR[0x130000]))
#define MCF_EPORT_EPDDR (*(vuint8 *)(void*)(&__IPSBAR[0x130002]))
#define MCF_EPORT_EPIER (*(vuint8 *)(void*)(&__IPSBAR[0x130003]))
#define MCF_EPORT_EPDR (*(vuint8 *)(void*)(&__IPSBAR[0x130004]))
#define MCF_EPORT_EPPDR (*(vuint8 *)(void*)(&__IPSBAR[0x130005]))
#define MCF_EPORT_EPFR (*(vuint8 *)(void*)(&__IPSBAR[0x130006]))
/* Bit definitions and macros for MCF_EPORT_EPPAR */
#define MCF_EPORT_EPPAR_EPPA1(x) (((x)&0x0003)<<2)
#define MCF_EPORT_EPPAR_EPPA2(x) (((x)&0x0003)<<4)
#define MCF_EPORT_EPPAR_EPPA3(x) (((x)&0x0003)<<6)
#define MCF_EPORT_EPPAR_EPPA4(x) (((x)&0x0003)<<8)
#define MCF_EPORT_EPPAR_EPPA5(x) (((x)&0x0003)<<10)
#define MCF_EPORT_EPPAR_EPPA6(x) (((x)&0x0003)<<12)
#define MCF_EPORT_EPPAR_EPPA7(x) (((x)&0x0003)<<14)
#define MCF_EPORT_EPPAR_EPPAx_LEVEL (0)
#define MCF_EPORT_EPPAR_EPPAx_RISING (1)
#define MCF_EPORT_EPPAR_EPPAx_FALLING (2)
#define MCF_EPORT_EPPAR_EPPAx_BOTH (3)
/* Bit definitions and macros for MCF_EPORT_EPDDR */
#define MCF_EPORT_EPDDR_EPDD1 (0x02)
#define MCF_EPORT_EPDDR_EPDD2 (0x04)
#define MCF_EPORT_EPDDR_EPDD3 (0x08)
#define MCF_EPORT_EPDDR_EPDD4 (0x10)
#define MCF_EPORT_EPDDR_EPDD5 (0x20)
#define MCF_EPORT_EPDDR_EPDD6 (0x40)
#define MCF_EPORT_EPDDR_EPDD7 (0x80)
/* Bit definitions and macros for MCF_EPORT_EPIER */
#define MCF_EPORT_EPIER_EPIE1 (0x02)
#define MCF_EPORT_EPIER_EPIE2 (0x04)
#define MCF_EPORT_EPIER_EPIE3 (0x08)
#define MCF_EPORT_EPIER_EPIE4 (0x10)
#define MCF_EPORT_EPIER_EPIE5 (0x20)
#define MCF_EPORT_EPIER_EPIE6 (0x40)
#define MCF_EPORT_EPIER_EPIE7 (0x80)
/* Bit definitions and macros for MCF_EPORT_EPDR */
#define MCF_EPORT_EPDR_EPD1 (0x02)
#define MCF_EPORT_EPDR_EPD2 (0x04)
#define MCF_EPORT_EPDR_EPD3 (0x08)
#define MCF_EPORT_EPDR_EPD4 (0x10)
#define MCF_EPORT_EPDR_EPD5 (0x20)
#define MCF_EPORT_EPDR_EPD6 (0x40)
#define MCF_EPORT_EPDR_EPD7 (0x80)
/* Bit definitions and macros for MCF_EPORT_EPPDR */
#define MCF_EPORT_EPPDR_EPPD1 (0x02)
#define MCF_EPORT_EPPDR_EPPD2 (0x04)
#define MCF_EPORT_EPPDR_EPPD3 (0x08)
#define MCF_EPORT_EPPDR_EPPD4 (0x10)
#define MCF_EPORT_EPPDR_EPPD5 (0x20)
#define MCF_EPORT_EPPDR_EPPD6 (0x40)
#define MCF_EPORT_EPPDR_EPPD7 (0x80)
/* Bit definitions and macros for MCF_EPORT_EPFR */
#define MCF_EPORT_EPFR_EPF1 (0x02)
#define MCF_EPORT_EPFR_EPF2 (0x04)
#define MCF_EPORT_EPFR_EPF3 (0x08)
#define MCF_EPORT_EPFR_EPF4 (0x10)
#define MCF_EPORT_EPFR_EPF5 (0x20)
#define MCF_EPORT_EPFR_EPF6 (0x40)
#define MCF_EPORT_EPFR_EPF7 (0x80)
/********************************************************************/
#endif /* __MCF523X_EPORT_H__ */

View File

@@ -0,0 +1,487 @@
/*
* File: mcf523x_etpu.h
* Purpose: Register and bit definitions for the MCF523X
*
* Notes:
*
*/
#ifndef __MCF523X_ETPU_H__
#define __MCF523X_ETPU_H__
/*********************************************************************
*
* enhanced Time Processor Unit (ETPU)
*
*********************************************************************/
/* Register read/write macros */
#define MCF_ETPU_EMCR (*(vuint32*)(void*)(&__IPSBAR[0x1D0000]))
#define MCF_ETPU_ECDCR (*(vuint32*)(void*)(&__IPSBAR[0x1D0004]))
#define MCF_ETPU_EMISCCR (*(vuint32*)(void*)(&__IPSBAR[0x1D000C]))
#define MCF_ETPU_ESCMODR (*(vuint32*)(void*)(&__IPSBAR[0x1D0010]))
#define MCF_ETPU_EECR (*(vuint32*)(void*)(&__IPSBAR[0x1D0014]))
#define MCF_ETPU_ETBCR (*(vuint32*)(void*)(&__IPSBAR[0x1D0020]))
#define MCF_ETPU_ETB1R (*(vuint32*)(void*)(&__IPSBAR[0x1D0024]))
#define MCF_ETPU_ETB2R (*(vuint32*)(void*)(&__IPSBAR[0x1D0028]))
#define MCF_ETPU_EREDCR (*(vuint32*)(void*)(&__IPSBAR[0x1D002C]))
#define MCF_ETPU_ECISR (*(vuint32*)(void*)(&__IPSBAR[0x1D0200]))
#define MCF_ETPU_ECDTRSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0210]))
#define MCF_ETPU_ECIOSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0220]))
#define MCF_ETPU_ECDTROSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0230]))
#define MCF_ETPU_ECIER (*(vuint32*)(void*)(&__IPSBAR[0x1D0240]))
#define MCF_ETPU_ECDTRER (*(vuint32*)(void*)(&__IPSBAR[0x1D0250]))
#define MCF_ETPU_ECPSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0280]))
#define MCF_ETPU_ECSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0290]))
#define MCF_ETPU_EC0SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D0404]))
#define MCF_ETPU_EC1SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D0414]))
#define MCF_ETPU_EC2SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D0424]))
#define MCF_ETPU_EC3SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D0434]))
#define MCF_ETPU_EC4SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D0444]))
#define MCF_ETPU_EC5SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D0454]))
#define MCF_ETPU_EC6SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D0464]))
#define MCF_ETPU_EC7SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D0474]))
#define MCF_ETPU_EC8SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D0484]))
#define MCF_ETPU_EC9SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D0494]))
#define MCF_ETPU_EC10SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D04A4]))
#define MCF_ETPU_EC11SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D04B4]))
#define MCF_ETPU_EC12SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D04C4]))
#define MCF_ETPU_EC13SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D04D4]))
#define MCF_ETPU_EC14SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D04E4]))
#define MCF_ETPU_EC15SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D04F4]))
#define MCF_ETPU_EC16SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D0504]))
#define MCF_ETPU_EC17SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D0514]))
#define MCF_ETPU_EC18SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D0524]))
#define MCF_ETPU_EC19SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D0534]))
#define MCF_ETPU_EC20SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D0544]))
#define MCF_ETPU_EC21SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D0554]))
#define MCF_ETPU_EC22SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D0564]))
#define MCF_ETPU_EC23SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D0574]))
#define MCF_ETPU_EC24SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D0584]))
#define MCF_ETPU_EC25SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D0594]))
#define MCF_ETPU_EC26SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D05A4]))
#define MCF_ETPU_EC27SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D05B4]))
#define MCF_ETPU_EC28SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D05C4]))
#define MCF_ETPU_EC29SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D05D4]))
#define MCF_ETPU_EC30SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D05E4]))
#define MCF_ETPU_EC31SCR (*(vuint32*)(void*)(&__IPSBAR[0x1D05F4]))
#define MCF_ETPU_ECnSCR(x) (*(vuint32*)(void*)(&__IPSBAR[0x1D0404+((x)*0x010)]))
#define MCF_ETPU_EC0CR (*(vuint32*)(void*)(&__IPSBAR[0x1D0400]))
#define MCF_ETPU_EC1CR (*(vuint32*)(void*)(&__IPSBAR[0x1D0410]))
#define MCF_ETPU_EC2CR (*(vuint32*)(void*)(&__IPSBAR[0x1D0420]))
#define MCF_ETPU_EC3CR (*(vuint32*)(void*)(&__IPSBAR[0x1D0430]))
#define MCF_ETPU_EC4CR (*(vuint32*)(void*)(&__IPSBAR[0x1D0440]))
#define MCF_ETPU_EC5CR (*(vuint32*)(void*)(&__IPSBAR[0x1D0450]))
#define MCF_ETPU_EC6CR (*(vuint32*)(void*)(&__IPSBAR[0x1D0460]))
#define MCF_ETPU_EC7CR (*(vuint32*)(void*)(&__IPSBAR[0x1D0470]))
#define MCF_ETPU_EC8CR (*(vuint32*)(void*)(&__IPSBAR[0x1D0480]))
#define MCF_ETPU_EC9CR (*(vuint32*)(void*)(&__IPSBAR[0x1D0490]))
#define MCF_ETPU_EC10CR (*(vuint32*)(void*)(&__IPSBAR[0x1D04A0]))
#define MCF_ETPU_EC11CR (*(vuint32*)(void*)(&__IPSBAR[0x1D04B0]))
#define MCF_ETPU_EC12CR (*(vuint32*)(void*)(&__IPSBAR[0x1D04C0]))
#define MCF_ETPU_EC13CR (*(vuint32*)(void*)(&__IPSBAR[0x1D04D0]))
#define MCF_ETPU_EC14CR (*(vuint32*)(void*)(&__IPSBAR[0x1D04E0]))
#define MCF_ETPU_EC15CR (*(vuint32*)(void*)(&__IPSBAR[0x1D04F0]))
#define MCF_ETPU_EC16CR (*(vuint32*)(void*)(&__IPSBAR[0x1D0500]))
#define MCF_ETPU_EC17CR (*(vuint32*)(void*)(&__IPSBAR[0x1D0510]))
#define MCF_ETPU_EC18CR (*(vuint32*)(void*)(&__IPSBAR[0x1D0520]))
#define MCF_ETPU_EC19CR (*(vuint32*)(void*)(&__IPSBAR[0x1D0530]))
#define MCF_ETPU_EC20CR (*(vuint32*)(void*)(&__IPSBAR[0x1D0540]))
#define MCF_ETPU_EC21CR (*(vuint32*)(void*)(&__IPSBAR[0x1D0550]))
#define MCF_ETPU_EC22CR (*(vuint32*)(void*)(&__IPSBAR[0x1D0560]))
#define MCF_ETPU_EC23CR (*(vuint32*)(void*)(&__IPSBAR[0x1D0570]))
#define MCF_ETPU_EC24CR (*(vuint32*)(void*)(&__IPSBAR[0x1D0580]))
#define MCF_ETPU_EC25CR (*(vuint32*)(void*)(&__IPSBAR[0x1D0590]))
#define MCF_ETPU_EC26CR (*(vuint32*)(void*)(&__IPSBAR[0x1D05A0]))
#define MCF_ETPU_EC27CR (*(vuint32*)(void*)(&__IPSBAR[0x1D05B0]))
#define MCF_ETPU_EC28CR (*(vuint32*)(void*)(&__IPSBAR[0x1D05C0]))
#define MCF_ETPU_EC29CR (*(vuint32*)(void*)(&__IPSBAR[0x1D05D0]))
#define MCF_ETPU_EC30CR (*(vuint32*)(void*)(&__IPSBAR[0x1D05E0]))
#define MCF_ETPU_EC31CR (*(vuint32*)(void*)(&__IPSBAR[0x1D05F0]))
#define MCF_ETPU_ECnCR(x) (*(vuint32*)(void*)(&__IPSBAR[0x1D0400+((x)*0x010)]))
#define MCF_ETPU_EC0HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0408]))
#define MCF_ETPU_EC1HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0418]))
#define MCF_ETPU_EC2HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0428]))
#define MCF_ETPU_EC3HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0438]))
#define MCF_ETPU_EC4HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0448]))
#define MCF_ETPU_EC5HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0458]))
#define MCF_ETPU_EC6HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0468]))
#define MCF_ETPU_EC7HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0478]))
#define MCF_ETPU_EC8HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0488]))
#define MCF_ETPU_EC9HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0498]))
#define MCF_ETPU_EC10HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D04A8]))
#define MCF_ETPU_EC11HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D04B8]))
#define MCF_ETPU_EC12HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D04C8]))
#define MCF_ETPU_EC13HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D04D8]))
#define MCF_ETPU_EC14HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D04E8]))
#define MCF_ETPU_EC15HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D04F8]))
#define MCF_ETPU_EC16HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0508]))
#define MCF_ETPU_EC17HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0518]))
#define MCF_ETPU_EC18HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0528]))
#define MCF_ETPU_EC19HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0538]))
#define MCF_ETPU_EC20HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0548]))
#define MCF_ETPU_EC21HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0558]))
#define MCF_ETPU_EC22HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0568]))
#define MCF_ETPU_EC23HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0578]))
#define MCF_ETPU_EC24HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0588]))
#define MCF_ETPU_EC25HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D0598]))
#define MCF_ETPU_EC26HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D05A8]))
#define MCF_ETPU_EC27HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D05B8]))
#define MCF_ETPU_EC28HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D05C8]))
#define MCF_ETPU_EC29HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D05D8]))
#define MCF_ETPU_EC30HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D05E8]))
#define MCF_ETPU_EC31HSSR (*(vuint32*)(void*)(&__IPSBAR[0x1D05F8]))
#define MCF_ETPU_ECnHSSR(x) (*(vuint32*)(void*)(&__IPSBAR[0x1D0408+((x)*0x010)]))
/* Bit definitions and macros for MCF_ETPU_EMCR */
#define MCF_ETPU_EMCR_GTBE (0x00000001)
#define MCF_ETPU_EMCR_VIS (0x00000040)
#define MCF_ETPU_EMCR_SCMMISEN (0x00000200)
#define MCF_ETPU_EMCR_SCMMISF (0x00000400)
#define MCF_ETPU_EMCR_SCMSIZE(x) (((x)&0x0000001F)<<16)
#define MCF_ETPU_EMCR_ILF2 (0x01000000)
#define MCF_ETPU_EMCR_ILF1 (0x02000000)
#define MCF_ETPU_EMCR_MGE2 (0x04000000)
#define MCF_ETPU_EMCR_MGE1 (0x08000000)
#define MCF_ETPU_EMCR_GEC (0x80000000)
/* Bit definitions and macros for MCF_ETPU_ECDCR */
#define MCF_ETPU_ECDCR_PARM1(x) (((x)&0x0000007F)<<0)
#define MCF_ETPU_ECDCR_WR (0x00000080)
#define MCF_ETPU_ECDCR_PARM0(x) (((x)&0x0000007F)<<8)
#define MCF_ETPU_ECDCR_PWIDTH (0x00008000)
#define MCF_ETPU_ECDCR_PBASE(x) (((x)&0x000003FF)<<16)
#define MCF_ETPU_ECDCR_CTBASE(x) (((x)&0x0000001F)<<26)
#define MCF_ETPU_ECDCR_STS (0x80000000)
/* Bit definitions and macros for MCF_ETPU_EECR */
#define MCF_ETPU_EECR_ETB(x) (((x)&0x0000001F)<<0)
#define MCF_ETPU_EECR_CDFC(x) (((x)&0x00000003)<<14)
#define MCF_ETPU_EECR_FPSK(x) (((x)&0x00000007)<<16)
#define MCF_ETPU_EECR_HLTF (0x00800000)
#define MCF_ETPU_EECR_STF (0x10000000)
#define MCF_ETPU_EECR_MDIS (0x40000000)
#define MCF_ETPU_EECR_FEND (0x80000000)
/* Bit definitions and macros for MCF_ETPU_ETBCR */
#define MCF_ETPU_ETBCR_TCR1P(x) (((x)&0x000000FF)<<0)
#define MCF_ETPU_ETBCR_TCR1CTL(x) (((x)&0x00000003)<<14)
#define MCF_ETPU_ETBCR_TCR2P(x) (((x)&0x0000003F)<<16)
#define MCF_ETPU_ETBCR_AM (0x02000000)
#define MCF_ETPU_ETBCR_TCRCF(x) (((x)&0x00000003)<<27)
#define MCF_ETPU_ETBCR_TCR2CTL(x) (((x)&0x00000007)<<29)
/* Bit definitions and macros for MCF_ETPU_ETB1R */
#define MCF_ETPU_ETB1R_TCR1(x) (((x)&0x00FFFFFF)<<0)
/* Bit definitions and macros for MCF_ETPU_ETB2R */
#define MCF_ETPU_ETB2R_TCR2(x) (((x)&0x00FFFFFF)<<0)
/* Bit definitions and macros for MCF_ETPU_EREDCR */
#define MCF_ETPU_EREDCR_SRV2(x) (((x)&0x0000000F)<<0)
#define MCF_ETPU_EREDCR_SERVER_ID2(x) (((x)&0x0000000F)<<8)
#define MCF_ETPU_EREDCR_RSC2 (0x00004000)
#define MCF_ETPU_EREDCR_REN2 (0x00008000)
#define MCF_ETPU_EREDCR_SRV1(x) (((x)&0x0000000F)<<16)
#define MCF_ETPU_EREDCR_SERVER_ID1(x) (((x)&0x0000000F)<<24)
#define MCF_ETPU_EREDCR_RSC1 (0x40000000)
#define MCF_ETPU_EREDCR_REN1 (0x80000000)
/* Bit definitions and macros for MCF_ETPU_ECISR */
#define MCF_ETPU_ECISR_CIS0 (0x00000001)
#define MCF_ETPU_ECISR_CIS1 (0x00000002)
#define MCF_ETPU_ECISR_CIS2 (0x00000004)
#define MCF_ETPU_ECISR_CIS3 (0x00000008)
#define MCF_ETPU_ECISR_CIS4 (0x00000010)
#define MCF_ETPU_ECISR_CIS5 (0x00000020)
#define MCF_ETPU_ECISR_CIS6 (0x00000040)
#define MCF_ETPU_ECISR_CIS7 (0x00000080)
#define MCF_ETPU_ECISR_CIS8 (0x00000100)
#define MCF_ETPU_ECISR_CIS9 (0x00000200)
#define MCF_ETPU_ECISR_CIS10 (0x00000400)
#define MCF_ETPU_ECISR_CIS11 (0x00000800)
#define MCF_ETPU_ECISR_CIS12 (0x00001000)
#define MCF_ETPU_ECISR_CIS13 (0x00002000)
#define MCF_ETPU_ECISR_CIS14 (0x00004000)
#define MCF_ETPU_ECISR_CIS15 (0x00008000)
#define MCF_ETPU_ECISR_CIS16 (0x00010000)
#define MCF_ETPU_ECISR_CIS17 (0x00020000)
#define MCF_ETPU_ECISR_CIS18 (0x00040000)
#define MCF_ETPU_ECISR_CIS19 (0x00080000)
#define MCF_ETPU_ECISR_CIS20 (0x00100000)
#define MCF_ETPU_ECISR_CIS21 (0x00200000)
#define MCF_ETPU_ECISR_CIS22 (0x00400000)
#define MCF_ETPU_ECISR_CIS23 (0x00800000)
#define MCF_ETPU_ECISR_CIS24 (0x01000000)
#define MCF_ETPU_ECISR_CIS25 (0x02000000)
#define MCF_ETPU_ECISR_CIS26 (0x04000000)
#define MCF_ETPU_ECISR_CIS27 (0x08000000)
#define MCF_ETPU_ECISR_CIS28 (0x10000000)
#define MCF_ETPU_ECISR_CIS29 (0x20000000)
#define MCF_ETPU_ECISR_CIS30 (0x40000000)
#define MCF_ETPU_ECISR_CIS31 (0x80000000)
/* Bit definitions and macros for MCF_ETPU_ECDTRSR */
#define MCF_ETPU_ECDTRSR_DTRS0 (0x00000001)
#define MCF_ETPU_ECDTRSR_DTRS1 (0x00000002)
#define MCF_ETPU_ECDTRSR_DTRS2 (0x00000004)
#define MCF_ETPU_ECDTRSR_DTRS3 (0x00000008)
#define MCF_ETPU_ECDTRSR_DTRS4 (0x00000010)
#define MCF_ETPU_ECDTRSR_DTRS5 (0x00000020)
#define MCF_ETPU_ECDTRSR_DTRS6 (0x00000040)
#define MCF_ETPU_ECDTRSR_DTRS7 (0x00000080)
#define MCF_ETPU_ECDTRSR_DTRS8 (0x00000100)
#define MCF_ETPU_ECDTRSR_DTRS9 (0x00000200)
#define MCF_ETPU_ECDTRSR_DTRS10 (0x00000400)
#define MCF_ETPU_ECDTRSR_DTRS11 (0x00000800)
#define MCF_ETPU_ECDTRSR_DTRS12 (0x00001000)
#define MCF_ETPU_ECDTRSR_DTRS13 (0x00002000)
#define MCF_ETPU_ECDTRSR_DTRS14 (0x00004000)
#define MCF_ETPU_ECDTRSR_DTRS15 (0x00008000)
#define MCF_ETPU_ECDTRSR_DTRS16 (0x00010000)
#define MCF_ETPU_ECDTRSR_DTRS17 (0x00020000)
#define MCF_ETPU_ECDTRSR_DTRS18 (0x00040000)
#define MCF_ETPU_ECDTRSR_DTRS19 (0x00080000)
#define MCF_ETPU_ECDTRSR_DTRS20 (0x00100000)
#define MCF_ETPU_ECDTRSR_DTRS21 (0x00200000)
#define MCF_ETPU_ECDTRSR_DTRS22 (0x00400000)
#define MCF_ETPU_ECDTRSR_DTRS23 (0x00800000)
#define MCF_ETPU_ECDTRSR_DTRS24 (0x01000000)
#define MCF_ETPU_ECDTRSR_DTRS25 (0x02000000)
#define MCF_ETPU_ECDTRSR_DTRS26 (0x04000000)
#define MCF_ETPU_ECDTRSR_DTRS27 (0x08000000)
#define MCF_ETPU_ECDTRSR_DTRS28 (0x10000000)
#define MCF_ETPU_ECDTRSR_DTRS29 (0x20000000)
#define MCF_ETPU_ECDTRSR_DTRS30 (0x40000000)
#define MCF_ETPU_ECDTRSR_DTRS31 (0x80000000)
/* Bit definitions and macros for MCF_ETPU_ECIOSR */
#define MCF_ETPU_ECIOSR_CIOS0 (0x00000001)
#define MCF_ETPU_ECIOSR_CIOS1 (0x00000002)
#define MCF_ETPU_ECIOSR_CIOS2 (0x00000004)
#define MCF_ETPU_ECIOSR_CIOS3 (0x00000008)
#define MCF_ETPU_ECIOSR_CIOS4 (0x00000010)
#define MCF_ETPU_ECIOSR_CIOS5 (0x00000020)
#define MCF_ETPU_ECIOSR_CIOS6 (0x00000040)
#define MCF_ETPU_ECIOSR_CIOS7 (0x00000080)
#define MCF_ETPU_ECIOSR_CIOS8 (0x00000100)
#define MCF_ETPU_ECIOSR_CIOS9 (0x00000200)
#define MCF_ETPU_ECIOSR_CIOS10 (0x00000400)
#define MCF_ETPU_ECIOSR_CIOS11 (0x00000800)
#define MCF_ETPU_ECIOSR_CIOS12 (0x00001000)
#define MCF_ETPU_ECIOSR_CIOS13 (0x00002000)
#define MCF_ETPU_ECIOSR_CIOS14 (0x00004000)
#define MCF_ETPU_ECIOSR_CIOS15 (0x00008000)
#define MCF_ETPU_ECIOSR_CIOS16 (0x00010000)
#define MCF_ETPU_ECIOSR_CIOS17 (0x00020000)
#define MCF_ETPU_ECIOSR_CIOS18 (0x00040000)
#define MCF_ETPU_ECIOSR_CIOS19 (0x00080000)
#define MCF_ETPU_ECIOSR_CIOS20 (0x00100000)
#define MCF_ETPU_ECIOSR_CIOS21 (0x00200000)
#define MCF_ETPU_ECIOSR_CIOS22 (0x00400000)
#define MCF_ETPU_ECIOSR_CIOS23 (0x00800000)
#define MCF_ETPU_ECIOSR_CIOS24 (0x01000000)
#define MCF_ETPU_ECIOSR_CIOS25 (0x02000000)
#define MCF_ETPU_ECIOSR_CIOS26 (0x04000000)
#define MCF_ETPU_ECIOSR_CIOS27 (0x08000000)
#define MCF_ETPU_ECIOSR_CIOS28 (0x10000000)
#define MCF_ETPU_ECIOSR_CIOS29 (0x20000000)
#define MCF_ETPU_ECIOSR_CIOS30 (0x40000000)
#define MCF_ETPU_ECIOSR_CIOS31 (0x80000000)
/* Bit definitions and macros for MCF_ETPU_ECDTROSR */
#define MCF_ETPU_ECDTROSR_DTROS0 (0x00000001)
#define MCF_ETPU_ECDTROSR_DTROS1 (0x00000002)
#define MCF_ETPU_ECDTROSR_DTROS2 (0x00000004)
#define MCF_ETPU_ECDTROSR_DTROS3 (0x00000008)
#define MCF_ETPU_ECDTROSR_DTROS4 (0x00000010)
#define MCF_ETPU_ECDTROSR_DTROS5 (0x00000020)
#define MCF_ETPU_ECDTROSR_DTROS6 (0x00000040)
#define MCF_ETPU_ECDTROSR_DTROS7 (0x00000080)
#define MCF_ETPU_ECDTROSR_DTROS8 (0x00000100)
#define MCF_ETPU_ECDTROSR_DTROS9 (0x00000200)
#define MCF_ETPU_ECDTROSR_DTROS10 (0x00000400)
#define MCF_ETPU_ECDTROSR_DTROS11 (0x00000800)
#define MCF_ETPU_ECDTROSR_DTROS12 (0x00001000)
#define MCF_ETPU_ECDTROSR_DTROS13 (0x00002000)
#define MCF_ETPU_ECDTROSR_DTROS14 (0x00004000)
#define MCF_ETPU_ECDTROSR_DTROS15 (0x00008000)
#define MCF_ETPU_ECDTROSR_DTROS16 (0x00010000)
#define MCF_ETPU_ECDTROSR_DTROS17 (0x00020000)
#define MCF_ETPU_ECDTROSR_DTROS18 (0x00040000)
#define MCF_ETPU_ECDTROSR_DTROS19 (0x00080000)
#define MCF_ETPU_ECDTROSR_DTROS20 (0x00100000)
#define MCF_ETPU_ECDTROSR_DTROS21 (0x00200000)
#define MCF_ETPU_ECDTROSR_DTROS22 (0x00400000)
#define MCF_ETPU_ECDTROSR_DTROS23 (0x00800000)
#define MCF_ETPU_ECDTROSR_DTROS24 (0x01000000)
#define MCF_ETPU_ECDTROSR_DTROS25 (0x02000000)
#define MCF_ETPU_ECDTROSR_DTROS26 (0x04000000)
#define MCF_ETPU_ECDTROSR_DTROS27 (0x08000000)
#define MCF_ETPU_ECDTROSR_DTROS28 (0x10000000)
#define MCF_ETPU_ECDTROSR_DTROS29 (0x20000000)
#define MCF_ETPU_ECDTROSR_DTROS30 (0x40000000)
#define MCF_ETPU_ECDTROSR_DTROS31 (0x80000000)
/* Bit definitions and macros for MCF_ETPU_ECIER */
#define MCF_ETPU_ECIER_CIE0 (0x00000001)
#define MCF_ETPU_ECIER_CIE1 (0x00000002)
#define MCF_ETPU_ECIER_CIE2 (0x00000004)
#define MCF_ETPU_ECIER_CIE3 (0x00000008)
#define MCF_ETPU_ECIER_CIE4 (0x00000010)
#define MCF_ETPU_ECIER_CIE5 (0x00000020)
#define MCF_ETPU_ECIER_CIE6 (0x00000040)
#define MCF_ETPU_ECIER_CIE7 (0x00000080)
#define MCF_ETPU_ECIER_CIE8 (0x00000100)
#define MCF_ETPU_ECIER_CIE9 (0x00000200)
#define MCF_ETPU_ECIER_CIE10 (0x00000400)
#define MCF_ETPU_ECIER_CIE11 (0x00000800)
#define MCF_ETPU_ECIER_CIE12 (0x00001000)
#define MCF_ETPU_ECIER_CIE13 (0x00002000)
#define MCF_ETPU_ECIER_CIE14 (0x00004000)
#define MCF_ETPU_ECIER_CIE15 (0x00008000)
#define MCF_ETPU_ECIER_CIE16 (0x00010000)
#define MCF_ETPU_ECIER_CIE17 (0x00020000)
#define MCF_ETPU_ECIER_CIE18 (0x00040000)
#define MCF_ETPU_ECIER_CIE19 (0x00080000)
#define MCF_ETPU_ECIER_CIE20 (0x00100000)
#define MCF_ETPU_ECIER_CIE21 (0x00200000)
#define MCF_ETPU_ECIER_CIE22 (0x00400000)
#define MCF_ETPU_ECIER_CIE23 (0x00800000)
#define MCF_ETPU_ECIER_CIE24 (0x01000000)
#define MCF_ETPU_ECIER_CIE25 (0x02000000)
#define MCF_ETPU_ECIER_CIE26 (0x04000000)
#define MCF_ETPU_ECIER_CIE27 (0x08000000)
#define MCF_ETPU_ECIER_CIE28 (0x10000000)
#define MCF_ETPU_ECIER_CIE29 (0x20000000)
#define MCF_ETPU_ECIER_CIE30 (0x40000000)
#define MCF_ETPU_ECIER_CIE31 (0x80000000)
/* Bit definitions and macros for MCF_ETPU_ECDTRER */
#define MCF_ETPU_ECDTRER_DTRE0 (0x00000001)
#define MCF_ETPU_ECDTRER_DTRE1 (0x00000002)
#define MCF_ETPU_ECDTRER_DTRE2 (0x00000004)
#define MCF_ETPU_ECDTRER_DTRE3 (0x00000008)
#define MCF_ETPU_ECDTRER_DTRE4 (0x00000010)
#define MCF_ETPU_ECDTRER_DTRE5 (0x00000020)
#define MCF_ETPU_ECDTRER_DTRE6 (0x00000040)
#define MCF_ETPU_ECDTRER_DTRE7 (0x00000080)
#define MCF_ETPU_ECDTRER_DTRE8 (0x00000100)
#define MCF_ETPU_ECDTRER_DTRE9 (0x00000200)
#define MCF_ETPU_ECDTRER_DTRE10 (0x00000400)
#define MCF_ETPU_ECDTRER_DTRE11 (0x00000800)
#define MCF_ETPU_ECDTRER_DTRE12 (0x00001000)
#define MCF_ETPU_ECDTRER_DTRE13 (0x00002000)
#define MCF_ETPU_ECDTRER_DTRE14 (0x00004000)
#define MCF_ETPU_ECDTRER_DTRE15 (0x00008000)
#define MCF_ETPU_ECDTRER_DTRE16 (0x00010000)
#define MCF_ETPU_ECDTRER_DTRE17 (0x00020000)
#define MCF_ETPU_ECDTRER_DTRE18 (0x00040000)
#define MCF_ETPU_ECDTRER_DTRE19 (0x00080000)
#define MCF_ETPU_ECDTRER_DTRE20 (0x00100000)
#define MCF_ETPU_ECDTRER_DTRE21 (0x00200000)
#define MCF_ETPU_ECDTRER_DTRE22 (0x00400000)
#define MCF_ETPU_ECDTRER_DTRE23 (0x00800000)
#define MCF_ETPU_ECDTRER_DTRE24 (0x01000000)
#define MCF_ETPU_ECDTRER_DTRE25 (0x02000000)
#define MCF_ETPU_ECDTRER_DTRE26 (0x04000000)
#define MCF_ETPU_ECDTRER_DTRE27 (0x08000000)
#define MCF_ETPU_ECDTRER_DTRE28 (0x10000000)
#define MCF_ETPU_ECDTRER_DTRE29 (0x20000000)
#define MCF_ETPU_ECDTRER_DTRE30 (0x40000000)
#define MCF_ETPU_ECDTRER_DTRE31 (0x80000000)
/* Bit definitions and macros for MCF_ETPU_ECPSSR */
#define MCF_ETPU_ECPSSR_SR0 (0x00000001)
#define MCF_ETPU_ECPSSR_SR1 (0x00000002)
#define MCF_ETPU_ECPSSR_SR2 (0x00000004)
#define MCF_ETPU_ECPSSR_SR3 (0x00000008)
#define MCF_ETPU_ECPSSR_SR4 (0x00000010)
#define MCF_ETPU_ECPSSR_SR5 (0x00000020)
#define MCF_ETPU_ECPSSR_SR6 (0x00000040)
#define MCF_ETPU_ECPSSR_SR7 (0x00000080)
#define MCF_ETPU_ECPSSR_SR8 (0x00000100)
#define MCF_ETPU_ECPSSR_SR9 (0x00000200)
#define MCF_ETPU_ECPSSR_SR10 (0x00000400)
#define MCF_ETPU_ECPSSR_SR11 (0x00000800)
#define MCF_ETPU_ECPSSR_SR12 (0x00001000)
#define MCF_ETPU_ECPSSR_SR13 (0x00002000)
#define MCF_ETPU_ECPSSR_SR14 (0x00004000)
#define MCF_ETPU_ECPSSR_SR15 (0x00008000)
#define MCF_ETPU_ECPSSR_SR16 (0x00010000)
#define MCF_ETPU_ECPSSR_SR17 (0x00020000)
#define MCF_ETPU_ECPSSR_SR18 (0x00040000)
#define MCF_ETPU_ECPSSR_SR19 (0x00080000)
#define MCF_ETPU_ECPSSR_SR20 (0x00100000)
#define MCF_ETPU_ECPSSR_SR21 (0x00200000)
#define MCF_ETPU_ECPSSR_SR22 (0x00400000)
#define MCF_ETPU_ECPSSR_SR23 (0x00800000)
#define MCF_ETPU_ECPSSR_SR24 (0x01000000)
#define MCF_ETPU_ECPSSR_SR25 (0x02000000)
#define MCF_ETPU_ECPSSR_SR26 (0x04000000)
#define MCF_ETPU_ECPSSR_SR27 (0x08000000)
#define MCF_ETPU_ECPSSR_SR28 (0x10000000)
#define MCF_ETPU_ECPSSR_SR29 (0x20000000)
#define MCF_ETPU_ECPSSR_SR30 (0x40000000)
#define MCF_ETPU_ECPSSR_SR31 (0x80000000)
/* Bit definitions and macros for MCF_ETPU_ECSSR */
#define MCF_ETPU_ECSSR_SS0 (0x00000001)
#define MCF_ETPU_ECSSR_SS1 (0x00000002)
#define MCF_ETPU_ECSSR_SS2 (0x00000004)
#define MCF_ETPU_ECSSR_SS3 (0x00000008)
#define MCF_ETPU_ECSSR_SS4 (0x00000010)
#define MCF_ETPU_ECSSR_SS5 (0x00000020)
#define MCF_ETPU_ECSSR_SS6 (0x00000040)
#define MCF_ETPU_ECSSR_SS7 (0x00000080)
#define MCF_ETPU_ECSSR_SS8 (0x00000100)
#define MCF_ETPU_ECSSR_SS9 (0x00000200)
#define MCF_ETPU_ECSSR_SS10 (0x00000400)
#define MCF_ETPU_ECSSR_SS11 (0x00000800)
#define MCF_ETPU_ECSSR_SS12 (0x00001000)
#define MCF_ETPU_ECSSR_SS13 (0x00002000)
#define MCF_ETPU_ECSSR_SS14 (0x00004000)
#define MCF_ETPU_ECSSR_SS15 (0x00008000)
#define MCF_ETPU_ECSSR_SS16 (0x00010000)
#define MCF_ETPU_ECSSR_SS17 (0x00020000)
#define MCF_ETPU_ECSSR_SS18 (0x00040000)
#define MCF_ETPU_ECSSR_SS19 (0x00080000)
#define MCF_ETPU_ECSSR_SS20 (0x00100000)
#define MCF_ETPU_ECSSR_SS21 (0x00200000)
#define MCF_ETPU_ECSSR_SS22 (0x00400000)
#define MCF_ETPU_ECSSR_SS23 (0x00800000)
#define MCF_ETPU_ECSSR_SS24 (0x01000000)
#define MCF_ETPU_ECSSR_SS25 (0x02000000)
#define MCF_ETPU_ECSSR_SS26 (0x04000000)
#define MCF_ETPU_ECSSR_SS27 (0x08000000)
#define MCF_ETPU_ECSSR_SS28 (0x10000000)
#define MCF_ETPU_ECSSR_SS29 (0x20000000)
#define MCF_ETPU_ECSSR_SS30 (0x40000000)
#define MCF_ETPU_ECSSR_SS31 (0x80000000)
/* Bit definitions and macros for MCF_ETPU_ECnSCR */
#define MCF_ETPU_ECnSCR_FM(x) (((x)&0x00000003)<<0)
#define MCF_ETPU_ECnSCR_OBE (0x00002000)
#define MCF_ETPU_ECnSCR_OPS (0x00004000)
#define MCF_ETPU_ECnSCR_IPS (0x00008000)
#define MCF_ETPU_ECnSCR_DTROS (0x00400000)
#define MCF_ETPU_ECnSCR_DTRS (0x00800000)
#define MCF_ETPU_ECnSCR_CIOS (0x40000000)
#define MCF_ETPU_ECnSCR_CIS (0x80000000)
/* Bit definitions and macros for MCF_ETPU_ECnCR */
#define MCF_ETPU_ECnCR_CPBA(x) (((x)&0x000007FF)<<0)
#define MCF_ETPU_ECnCR_OPOL (0x00004000)
#define MCF_ETPU_ECnCR_ODIS (0x00008000)
#define MCF_ETPU_ECnCR_CFS(x) (((x)&0x0000001F)<<16)
#define MCF_ETPU_ECnCR_ETCS (0x01000000)
#define MCF_ETPU_ECnCR_CPR(x) (((x)&0x00000003)<<28)
#define MCF_ETPU_ECnCR_DTRE (0x40000000)
#define MCF_ETPU_ECnCR_CIE (0x80000000)
/* Bit definitions and macros for MCF_ETPU_ECnHSSR */
#define MCF_ETPU_ECnHSSR_HSR(x) (((x)&0x00000007)<<0)
/********************************************************************/
#endif /* __MCF523X_ETPU_H__ */

View File

@@ -0,0 +1,202 @@
/*
* File: mcf523x_fec.h
* Purpose: Register and bit definitions for the MCF523X
*
* Notes:
*
*/
#ifndef __MCF523X_FEC_H__
#define __MCF523X_FEC_H__
/*********************************************************************
*
* Fast Ethernet Controller (FEC)
*
*********************************************************************/
/* Register read/write macros */
#define MCF_FEC_EIR (*(vuint32*)(void*)(&__IPSBAR[0x001004]))
#define MCF_FEC_EIMR (*(vuint32*)(void*)(&__IPSBAR[0x001008]))
#define MCF_FEC_RDAR (*(vuint32*)(void*)(&__IPSBAR[0x001010]))
#define MCF_FEC_TDAR (*(vuint32*)(void*)(&__IPSBAR[0x001014]))
#define MCF_FEC_ECR (*(vuint32*)(void*)(&__IPSBAR[0x001024]))
#define MCF_FEC_MMFR (*(vuint32*)(void*)(&__IPSBAR[0x001040]))
#define MCF_FEC_MSCR (*(vuint32*)(void*)(&__IPSBAR[0x001044]))
#define MCF_FEC_MIBC (*(vuint32*)(void*)(&__IPSBAR[0x001064]))
#define MCF_FEC_RCR (*(vuint32*)(void*)(&__IPSBAR[0x001084]))
#define MCF_FEC_TCR (*(vuint32*)(void*)(&__IPSBAR[0x0010C4]))
#define MCF_FEC_PALR (*(vuint32*)(void*)(&__IPSBAR[0x0010E4]))
#define MCF_FEC_PAUR (*(vuint32*)(void*)(&__IPSBAR[0x0010E8]))
#define MCF_FEC_OPD (*(vuint32*)(void*)(&__IPSBAR[0x0010EC]))
#define MCF_FEC_IAUR (*(vuint32*)(void*)(&__IPSBAR[0x001118]))
#define MCF_FEC_IALR (*(vuint32*)(void*)(&__IPSBAR[0x00111C]))
#define MCF_FEC_GAUR (*(vuint32*)(void*)(&__IPSBAR[0x001120]))
#define MCF_FEC_GALR (*(vuint32*)(void*)(&__IPSBAR[0x001124]))
#define MCF_FEC_TFWR (*(vuint32*)(void*)(&__IPSBAR[0x001144]))
#define MCF_FEC_FRBR (*(vuint32*)(void*)(&__IPSBAR[0x00114C]))
#define MCF_FEC_FRSR (*(vuint32*)(void*)(&__IPSBAR[0x001150]))
#define MCF_FEC_ERDSR (*(vuint32*)(void*)(&__IPSBAR[0x001180]))
#define MCF_FEC_ETDSR (*(vuint32*)(void*)(&__IPSBAR[0x001184]))
#define MCF_FEC_EMRBR (*(vuint32*)(void*)(&__IPSBAR[0x001188]))
#define MCF_FEC_RMON_T_DROP (*(vuint32*)(void*)(&__IPSBAR[0x001200]))
#define MCF_FEC_RMON_T_PACKETS (*(vuint32*)(void*)(&__IPSBAR[0x001204]))
#define MCF_FEC_RMON_T_BC_PKT (*(vuint32*)(void*)(&__IPSBAR[0x001208]))
#define MCF_FEC_RMON_T_MC_PKT (*(vuint32*)(void*)(&__IPSBAR[0x00120C]))
#define MCF_FEC_RMON_T_CRC_ALIGN (*(vuint32*)(void*)(&__IPSBAR[0x001210]))
#define MCF_FEC_RMON_T_UNDERSIZE (*(vuint32*)(void*)(&__IPSBAR[0x001214]))
#define MCF_FEC_RMON_T_OVERSIZE (*(vuint32*)(void*)(&__IPSBAR[0x001218]))
#define MCF_FEC_RMON_T_FRAG (*(vuint32*)(void*)(&__IPSBAR[0x00121C]))
#define MCF_FEC_RMON_T_JAB (*(vuint32*)(void*)(&__IPSBAR[0x001220]))
#define MCF_FEC_RMON_T_COL (*(vuint32*)(void*)(&__IPSBAR[0x001224]))
#define MCF_FEC_RMON_T_P64 (*(vuint32*)(void*)(&__IPSBAR[0x001228]))
#define MCF_FEC_RMON_T_P65TO127 (*(vuint32*)(void*)(&__IPSBAR[0x00122C]))
#define MCF_FEC_RMON_T_P128TO255 (*(vuint32*)(void*)(&__IPSBAR[0x001230]))
#define MCF_FEC_RMON_T_P256TO511 (*(vuint32*)(void*)(&__IPSBAR[0x001234]))
#define MCF_FEC_RMON_T_P512TO1023 (*(vuint32*)(void*)(&__IPSBAR[0x001238]))
#define MCF_FEC_RMON_T_P1024TO2047 (*(vuint32*)(void*)(&__IPSBAR[0x00123C]))
#define MCF_FEC_RMON_T_P_GTE2048 (*(vuint32*)(void*)(&__IPSBAR[0x001240]))
#define MCF_FEC_RMON_T_OCTETS (*(vuint32*)(void*)(&__IPSBAR[0x001244]))
#define MCF_FEC_IEEE_T_DROP (*(vuint32*)(void*)(&__IPSBAR[0x001248]))
#define MCF_FEC_IEEE_T_FRAME_OK (*(vuint32*)(void*)(&__IPSBAR[0x00124C]))
#define MCF_FEC_IEEE_T_1COL (*(vuint32*)(void*)(&__IPSBAR[0x001250]))
#define MCF_FEC_IEEE_T_MCOL (*(vuint32*)(void*)(&__IPSBAR[0x001254]))
#define MCF_FEC_IEEE_T_DEF (*(vuint32*)(void*)(&__IPSBAR[0x001258]))
#define MCF_FEC_IEEE_T_LCOL (*(vuint32*)(void*)(&__IPSBAR[0x00125C]))
#define MCF_FEC_IEEE_T_EXCOL (*(vuint32*)(void*)(&__IPSBAR[0x001260]))
#define MCF_FEC_IEEE_T_MACERR (*(vuint32*)(void*)(&__IPSBAR[0x001264]))
#define MCF_FEC_IEEE_T_CSERR (*(vuint32*)(void*)(&__IPSBAR[0x001268]))
#define MCF_FEC_IEEE_T_SQE (*(vuint32*)(void*)(&__IPSBAR[0x00126C]))
#define MCF_FEC_IEEE_T_FDXFC (*(vuint32*)(void*)(&__IPSBAR[0x001270]))
#define MCF_FEC_IEEE_T_OCTETS_OK (*(vuint32*)(void*)(&__IPSBAR[0x001274]))
#define MCF_FEC_RMON_R_PACKETS (*(vuint32*)(void*)(&__IPSBAR[0x001284]))
#define MCF_FEC_RMON_R_BC_PKT (*(vuint32*)(void*)(&__IPSBAR[0x001288]))
#define MCF_FEC_RMON_R_MC_PKT (*(vuint32*)(void*)(&__IPSBAR[0x00128C]))
#define MCF_FEC_RMON_R_CRC_ALIGN (*(vuint32*)(void*)(&__IPSBAR[0x001290]))
#define MCF_FEC_RMON_R_UNDERSIZE (*(vuint32*)(void*)(&__IPSBAR[0x001294]))
#define MCF_FEC_RMON_R_OVERSIZE (*(vuint32*)(void*)(&__IPSBAR[0x001298]))
#define MCF_FEC_RMON_R_FRAG (*(vuint32*)(void*)(&__IPSBAR[0x00129C]))
#define MCF_FEC_RMON_R_JAB (*(vuint32*)(void*)(&__IPSBAR[0x0012A0]))
#define MCF_FEC_RMON_R_RESVD_0 (*(vuint32*)(void*)(&__IPSBAR[0x0012A4]))
#define MCF_FEC_RMON_R_P64 (*(vuint32*)(void*)(&__IPSBAR[0x0012A8]))
#define MCF_FEC_RMON_R_P65TO127 (*(vuint32*)(void*)(&__IPSBAR[0x0012AC]))
#define MCF_FEC_RMON_R_P128TO255 (*(vuint32*)(void*)(&__IPSBAR[0x0012B0]))
#define MCF_FEC_RMON_R_P256TO511 (*(vuint32*)(void*)(&__IPSBAR[0x0012B4]))
#define MCF_FEC_RMON_R_512TO1023 (*(vuint32*)(void*)(&__IPSBAR[0x0012B8]))
#define MCF_FEC_RMON_R_P_GTE2048 (*(vuint32*)(void*)(&__IPSBAR[0x0012C0]))
#define MCF_FEC_RMON_R_1024TO2047 (*(vuint32*)(void*)(&__IPSBAR[0x0012BC]))
#define MCF_FEC_RMON_R_OCTETS (*(vuint32*)(void*)(&__IPSBAR[0x0012C4]))
#define MCF_FEC_IEEE_R_DROP (*(vuint32*)(void*)(&__IPSBAR[0x0012C8]))
#define MCF_FEC_IEEE_R_FRAME_OK (*(vuint32*)(void*)(&__IPSBAR[0x0012CC]))
#define MCF_FEC_IEEE_R_CRC (*(vuint32*)(void*)(&__IPSBAR[0x0012D0]))
#define MCF_FEC_IEEE_R_ALIGN (*(vuint32*)(void*)(&__IPSBAR[0x0012D4]))
#define MCF_FEC_IEEE_R_MACERR (*(vuint32*)(void*)(&__IPSBAR[0x0012D8]))
#define MCF_FEC_IEEE_R_FDXFC (*(vuint32*)(void*)(&__IPSBAR[0x0012DC]))
#define MCF_FEC_IEEE_R_OCTETS_OK (*(vuint32*)(void*)(&__IPSBAR[0x0012E0]))
/* Bit definitions and macros for MCF_FEC_EIR */
#define MCF_FEC_EIR_UN (0x00080000)
#define MCF_FEC_EIR_RL (0x00100000)
#define MCF_FEC_EIR_LC (0x00200000)
#define MCF_FEC_EIR_EBERR (0x00400000)
#define MCF_FEC_EIR_MII (0x00800000)
#define MCF_FEC_EIR_RXB (0x01000000)
#define MCF_FEC_EIR_RXF (0x02000000)
#define MCF_FEC_EIR_TXB (0x04000000)
#define MCF_FEC_EIR_TXF (0x08000000)
#define MCF_FEC_EIR_GRA (0x10000000)
#define MCF_FEC_EIR_BABT (0x20000000)
#define MCF_FEC_EIR_BABR (0x40000000)
#define MCF_FEC_EIR_HBERR (0x80000000)
/* Bit definitions and macros for MCF_FEC_EIMR */
#define MCF_FEC_EIMR_UN (0x00080000)
#define MCF_FEC_EIMR_RL (0x00100000)
#define MCF_FEC_EIMR_LC (0x00200000)
#define MCF_FEC_EIMR_EBERR (0x00400000)
#define MCF_FEC_EIMR_MII (0x00800000)
#define MCF_FEC_EIMR_RXB (0x01000000)
#define MCF_FEC_EIMR_RXF (0x02000000)
#define MCF_FEC_EIMR_TXB (0x04000000)
#define MCF_FEC_EIMR_TXF (0x08000000)
#define MCF_FEC_EIMR_GRA (0x10000000)
#define MCF_FEC_EIMR_BABT (0x20000000)
#define MCF_FEC_EIMR_BABR (0x40000000)
#define MCF_FEC_EIMR_HBERR (0x80000000)
/* Bit definitions and macros for MCF_FEC_RDAR */
#define MCF_FEC_RDAR_R_DES_ACTIVE (0x01000000)
/* Bit definitions and macros for MCF_FEC_TDAR */
#define MCF_FEC_TDAR_X_DES_ACTIVE (0x01000000)
/* Bit definitions and macros for MCF_FEC_ECR */
#define MCF_FEC_ECR_RESET (0x00000001)
#define MCF_FEC_ECR_ETHER_EN (0x00000002)
/* Bit definitions and macros for MCF_FEC_MMFR */
#define MCF_FEC_MMFR_DATA(x) (((x)&0x0000FFFF)<<0)
#define MCF_FEC_MMFR_TA(x) (((x)&0x00000003)<<16)
#define MCF_FEC_MMFR_RA(x) (((x)&0x0000001F)<<18)
#define MCF_FEC_MMFR_PA(x) (((x)&0x0000001F)<<23)
#define MCF_FEC_MMFR_OP(x) (((x)&0x00000003)<<28)
#define MCF_FEC_MMFR_ST(x) (((x)&0x00000003)<<30)
#define MCF_FEC_MMFR_ST_01 (0x40000000)
#define MCF_FEC_MMFR_OP_READ (0x20000000)
#define MCF_FEC_MMFR_OP_WRITE (0x10000000)
#define MCF_FEC_MMFR_TA_10 (0x00020000)
/* Bit definitions and macros for MCF_FEC_MSCR */
#define MCF_FEC_MSCR_MII_SPEED(x) (((x)&0x0000003F)<<1)
#define MCF_FEC_MSCR_DIS_PREAMBLE (0x00000080)
/* Bit definitions and macros for MCF_FEC_MIBC */
#define MCF_FEC_MIBC_MIB_IDLE (0x40000000)
#define MCF_FEC_MIBC_MIB_DISABLE (0x80000000)
/* Bit definitions and macros for MCF_FEC_RCR */
#define MCF_FEC_RCR_LOOP (0x00000001)
#define MCF_FEC_RCR_DRT (0x00000002)
#define MCF_FEC_RCR_MII_MODE (0x00000004)
#define MCF_FEC_RCR_PROM (0x00000008)
#define MCF_FEC_RCR_BC_REJ (0x00000010)
#define MCF_FEC_RCR_FCE (0x00000020)
#define MCF_FEC_RCR_MAX_FL(x) (((x)&0x000007FF)<<16)
/* Bit definitions and macros for MCF_FEC_TCR */
#define MCF_FEC_TCR_GTS (0x00000001)
#define MCF_FEC_TCR_HBC (0x00000002)
#define MCF_FEC_TCR_FDEN (0x00000004)
#define MCF_FEC_TCR_TFC_PAUSE (0x00000008)
#define MCF_FEC_TCR_RFC_PAUSE (0x00000010)
/* Bit definitions and macros for MCF_FEC_PAUR */
#define MCF_FEC_PAUR_TYPE(x) (((x)&0x0000FFFF)<<0)
#define MCF_FEC_PAUR_PADDR2(x) (((x)&0x0000FFFF)<<16)
/* Bit definitions and macros for MCF_FEC_OPD */
#define MCF_FEC_OPD_PAUSE_DUR(x) (((x)&0x0000FFFF)<<0)
#define MCF_FEC_OPD_OPCODE(x) (((x)&0x0000FFFF)<<16)
/* Bit definitions and macros for MCF_FEC_TFWR */
#define MCF_FEC_TFWR_X_WMRK(x) (((x)&0x00000003)<<0)
/* Bit definitions and macros for MCF_FEC_FRBR */
#define MCF_FEC_FRBR_R_BOUND(x) (((x)&0x000000FF)<<2)
/* Bit definitions and macros for MCF_FEC_FRSR */
#define MCF_FEC_FRSR_R_FSTART(x) (((x)&0x000000FF)<<2)
/* Bit definitions and macros for MCF_FEC_ERDSR */
#define MCF_FEC_ERDSR_R_DES_START(x) (((x)&0x3FFFFFFF)<<2)
/* Bit definitions and macros for MCF_FEC_ETDSR */
#define MCF_FEC_ETDSR_X_DES_START(x) (((x)&0x3FFFFFFF)<<2)
/* Bit definitions and macros for MCF_FEC_EMRBR */
#define MCF_FEC_EMRBR_R_BUF_SIZE(x) (((x)&0x0000007F)<<4)
/********************************************************************/
#endif /* __MCF523X_FEC_H__ */

View File

@@ -0,0 +1,49 @@
/*
* File: mcf523x_fmpll.h
* Purpose: Register and bit definitions for the MCF523X
*
* Notes:
*
*/
#ifndef __MCF523X_FMPLL_H__
#define __MCF523X_FMPLL_H__
/*********************************************************************
*
* Frequency Modulated Phase Locked Loop (FMPLL)
*
*********************************************************************/
/* Register read/write macros */
#define MCF_FMPLL_SYNCR (*(vuint32*)(void*)(&__IPSBAR[0x120000]))
#define MCF_FMPLL_SYNSR (*(vuint32*)(void*)(&__IPSBAR[0x120004]))
/* Bit definitions and macros for MCF_FMPLL_SYNCR */
#define MCF_FMPLL_SYNCR_EXP(x) (((x)&0x000003FF)<<0)
#define MCF_FMPLL_SYNCR_DEPTH(x) (((x)&0x00000003)<<10)
#define MCF_FMPLL_SYNCR_RATE (0x00001000)
#define MCF_FMPLL_SYNCR_LOCIRQ (0x00002000)
#define MCF_FMPLL_SYNCR_LOLIRQ (0x00004000)
#define MCF_FMPLL_SYNCR_DISCLK (0x00008000)
#define MCF_FMPLL_SYNCR_LOCRE (0x00010000)
#define MCF_FMPLL_SYNCR_LOLRE (0x00020000)
#define MCF_FMPLL_SYNCR_LOCEN (0x00040000)
#define MCF_FMPLL_SYNCR_RFD(x) (((x)&0x00000007)<<19)
#define MCF_FMPLL_SYNCR_MFD(x) (((x)&0x00000007)<<24)
/* Bit definitions and macros for MCF_FMPLL_SYNSR */
#define MCF_FMPLL_SYNSR_CALPASS (0x00000001)
#define MCF_FMPLL_SYNSR_CALDONE (0x00000002)
#define MCF_FMPLL_SYNSR_LOCF (0x00000004)
#define MCF_FMPLL_SYNSR_LOCK (0x00000008)
#define MCF_FMPLL_SYNSR_LOCKS (0x00000010)
#define MCF_FMPLL_SYNSR_PLLREF (0x00000020)
#define MCF_FMPLL_SYNSR_PLLSEL (0x00000040)
#define MCF_FMPLL_SYNSR_MODE (0x00000080)
#define MCF_FMPLL_SYNSR_LOC (0x00000100)
#define MCF_FMPLL_SYNSR_LOLF (0x00000200)
/********************************************************************/
#endif /* __MCF523X_FMPLL_H__ */

View File

@@ -0,0 +1,670 @@
/*
* File: mcf523x_gpio.h
* Purpose: Register and bit definitions for the MCF523X
*
* Notes:
*
*/
#ifndef __MCF523X_GPIO_H__
#define __MCF523X_GPIO_H__
/*********************************************************************
*
* General Purpose I/O (GPIO)
*
*********************************************************************/
/* Register read/write macros */
#define MCF_GPIO_PODR_ADDR (*(vuint8 *)(void*)(&__IPSBAR[0x100000]))
#define MCF_GPIO_PODR_DATAH (*(vuint8 *)(void*)(&__IPSBAR[0x100001]))
#define MCF_GPIO_PODR_DATAL (*(vuint8 *)(void*)(&__IPSBAR[0x100002]))
#define MCF_GPIO_PODR_BUSCTL (*(vuint8 *)(void*)(&__IPSBAR[0x100003]))
#define MCF_GPIO_PODR_BS (*(vuint8 *)(void*)(&__IPSBAR[0x100004]))
#define MCF_GPIO_PODR_CS (*(vuint8 *)(void*)(&__IPSBAR[0x100005]))
#define MCF_GPIO_PODR_SDRAM (*(vuint8 *)(void*)(&__IPSBAR[0x100006]))
#define MCF_GPIO_PODR_FECI2C (*(vuint8 *)(void*)(&__IPSBAR[0x100007]))
#define MCF_GPIO_PODR_UARTH (*(vuint8 *)(void*)(&__IPSBAR[0x100008]))
#define MCF_GPIO_PODR_UARTL (*(vuint8 *)(void*)(&__IPSBAR[0x100009]))
#define MCF_GPIO_PODR_QSPI (*(vuint8 *)(void*)(&__IPSBAR[0x10000A]))
#define MCF_GPIO_PODR_TIMER (*(vuint8 *)(void*)(&__IPSBAR[0x10000B]))
#define MCF_GPIO_PODR_ETPU (*(vuint8 *)(void*)(&__IPSBAR[0x10000C]))
#define MCF_GPIO_PDDR_APDDR (*(vuint8 *)(void*)(&__IPSBAR[0x100010]))
#define MCF_GPIO_PDDR_DATAH (*(vuint8 *)(void*)(&__IPSBAR[0x100011]))
#define MCF_GPIO_PDDR_DATAL (*(vuint8 *)(void*)(&__IPSBAR[0x100012]))
#define MCF_GPIO_PDDR_BUSCTL (*(vuint8 *)(void*)(&__IPSBAR[0x100013]))
#define MCF_GPIO_PDDR_BS (*(vuint8 *)(void*)(&__IPSBAR[0x100014]))
#define MCF_GPIO_PDDR_CS (*(vuint8 *)(void*)(&__IPSBAR[0x100015]))
#define MCF_GPIO_PDDR_SDRAM (*(vuint8 *)(void*)(&__IPSBAR[0x100016]))
#define MCF_GPIO_PDDR_FECI2C (*(vuint8 *)(void*)(&__IPSBAR[0x100017]))
#define MCF_GPIO_PDDR_UARTH (*(vuint8 *)(void*)(&__IPSBAR[0x100018]))
#define MCF_GPIO_PDDR_UARTL (*(vuint8 *)(void*)(&__IPSBAR[0x100019]))
#define MCF_GPIO_PDDR_QSPI (*(vuint8 *)(void*)(&__IPSBAR[0x10001A]))
#define MCF_GPIO_PDDR_TIMER (*(vuint8 *)(void*)(&__IPSBAR[0x10001B]))
#define MCF_GPIO_PDDR_ETPU (*(vuint8 *)(void*)(&__IPSBAR[0x10001C]))
#define MCF_GPIO_PPDSDR_ADDR (*(vuint8 *)(void*)(&__IPSBAR[0x100020]))
#define MCF_GPIO_PPDSDR_DATAH (*(vuint8 *)(void*)(&__IPSBAR[0x100021]))
#define MCF_GPIO_PPDSDR_DATAL (*(vuint8 *)(void*)(&__IPSBAR[0x100022]))
#define MCF_GPIO_PPDSDR_BUSCTL (*(vuint8 *)(void*)(&__IPSBAR[0x100023]))
#define MCF_GPIO_PPDSDR_BS (*(vuint8 *)(void*)(&__IPSBAR[0x100024]))
#define MCF_GPIO_PPDSDR_FECI2C (*(vuint8 *)(void*)(&__IPSBAR[0x100027]))
#define MCF_GPIO_PPDSDR_CS (*(vuint8 *)(void*)(&__IPSBAR[0x100025]))
#define MCF_GPIO_PPDSDR_SDRAM (*(vuint8 *)(void*)(&__IPSBAR[0x100026]))
#define MCF_GPIO_PPDSDR_UARTH (*(vuint8 *)(void*)(&__IPSBAR[0x100028]))
#define MCF_GPIO_PPDSDR_UARTL (*(vuint8 *)(void*)(&__IPSBAR[0x100029]))
#define MCF_GPIO_PPDSDR_QSPI (*(vuint8 *)(void*)(&__IPSBAR[0x10002A]))
#define MCF_GPIO_PPDSDR_TIMER (*(vuint8 *)(void*)(&__IPSBAR[0x10002B]))
#define MCF_GPIO_PPDSDR_ETPU (*(vuint8 *)(void*)(&__IPSBAR[0x10002C]))
#define MCF_GPIO_PCLRR_ADDR (*(vuint8 *)(void*)(&__IPSBAR[0x100030]))
#define MCF_GPIO_PCLRR_DATAH (*(vuint8 *)(void*)(&__IPSBAR[0x100031]))
#define MCF_GPIO_PCLRR_DATAL (*(vuint8 *)(void*)(&__IPSBAR[0x100032]))
#define MCF_GPIO_PCLRR_BUSCTL (*(vuint8 *)(void*)(&__IPSBAR[0x100033]))
#define MCF_GPIO_PCLRR_BS (*(vuint8 *)(void*)(&__IPSBAR[0x100034]))
#define MCF_GPIO_PCLRR_CS (*(vuint8 *)(void*)(&__IPSBAR[0x100035]))
#define MCF_GPIO_PCLRR_SDRAM (*(vuint8 *)(void*)(&__IPSBAR[0x100036]))
#define MCF_GPIO_PCLRR_FECI2C (*(vuint8 *)(void*)(&__IPSBAR[0x100037]))
#define MCF_GPIO_PCLRR_UARTH (*(vuint8 *)(void*)(&__IPSBAR[0x100038]))
#define MCF_GPIO_PCLRR_UARTL (*(vuint8 *)(void*)(&__IPSBAR[0x100039]))
#define MCF_GPIO_PCLRR_QSPI (*(vuint8 *)(void*)(&__IPSBAR[0x10003A]))
#define MCF_GPIO_PCLRR_TIMER (*(vuint8 *)(void*)(&__IPSBAR[0x10003B]))
#define MCF_GPIO_PCLRR_ETPU (*(vuint8 *)(void*)(&__IPSBAR[0x10003C]))
#define MCF_GPIO_PAR_AD (*(vuint8 *)(void*)(&__IPSBAR[0x100040]))
#define MCF_GPIO_PAR_BUSCTL (*(vuint16*)(void*)(&__IPSBAR[0x100042]))
#define MCF_GPIO_PAR_BS (*(vuint8 *)(void*)(&__IPSBAR[0x100044]))
#define MCF_GPIO_PAR_CS (*(vuint8 *)(void*)(&__IPSBAR[0x100045]))
#define MCF_GPIO_PAR_SDRAM (*(vuint8 *)(void*)(&__IPSBAR[0x100046]))
#define MCF_GPIO_PAR_FECI2C (*(vuint8 *)(void*)(&__IPSBAR[0x100047]))
#define MCF_GPIO_PAR_UART (*(vuint16*)(void*)(&__IPSBAR[0x100048]))
#define MCF_GPIO_PAR_QSPI (*(vuint8 *)(void*)(&__IPSBAR[0x10004A]))
#define MCF_GPIO_PAR_TIMER (*(vuint16*)(void*)(&__IPSBAR[0x10004C]))
#define MCF_GPIO_PAR_ETPU (*(vuint8 *)(void*)(&__IPSBAR[0x10004E]))
#define MCF_GPIO_DSCR_EIM (*(vuint8 *)(void*)(&__IPSBAR[0x100050]))
#define MCF_GPIO_DSCR_ETPU (*(vuint8 *)(void*)(&__IPSBAR[0x100051]))
#define MCF_GPIO_DSCR_FECI2C (*(vuint8 *)(void*)(&__IPSBAR[0x100052]))
#define MCF_GPIO_DSCR_UART (*(vuint8 *)(void*)(&__IPSBAR[0x100053]))
#define MCF_GPIO_DSCR_QSPI (*(vuint8 *)(void*)(&__IPSBAR[0x100054]))
#define MCF_GPIO_DSCR_TIMER (*(vuint8 *)(void*)(&__IPSBAR[0x100055]))
/* Bit definitions and macros for MCF_GPIO_PODR_ADDR */
#define MCF_GPIO_PODR_ADDR_PODR_ADDR5 (0x20)
#define MCF_GPIO_PODR_ADDR_PODR_ADDR6 (0x40)
#define MCF_GPIO_PODR_ADDR_PODR_ADDR7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PODR_DATAH */
#define MCF_GPIO_PODR_DATAH_PODR_DATAH0 (0x01)
#define MCF_GPIO_PODR_DATAH_PODR_DATAH1 (0x02)
#define MCF_GPIO_PODR_DATAH_PODR_DATAH2 (0x04)
#define MCF_GPIO_PODR_DATAH_PODR_DATAH3 (0x08)
#define MCF_GPIO_PODR_DATAH_PODR_DATAH4 (0x10)
#define MCF_GPIO_PODR_DATAH_PODR_DATAH5 (0x20)
#define MCF_GPIO_PODR_DATAH_PODR_DATAH6 (0x40)
#define MCF_GPIO_PODR_DATAH_PODR_DATAH7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PODR_DATAL */
#define MCF_GPIO_PODR_DATAL_PODR_DATAL0 (0x01)
#define MCF_GPIO_PODR_DATAL_PODR_DATAL1 (0x02)
#define MCF_GPIO_PODR_DATAL_PODR_DATAL2 (0x04)
#define MCF_GPIO_PODR_DATAL_PODR_DATAL3 (0x08)
#define MCF_GPIO_PODR_DATAL_PODR_DATAL4 (0x10)
#define MCF_GPIO_PODR_DATAL_PODR_DATAL5 (0x20)
#define MCF_GPIO_PODR_DATAL_PODR_DATAL6 (0x40)
#define MCF_GPIO_PODR_DATAL_PODR_DATAL7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PODR_BUSCTL */
#define MCF_GPIO_PODR_BUSCTL_PODR_BUSCTL0 (0x01)
#define MCF_GPIO_PODR_BUSCTL_PODR_BUSCTL1 (0x02)
#define MCF_GPIO_PODR_BUSCTL_PODR_BUSCTL2 (0x04)
#define MCF_GPIO_PODR_BUSCTL_PODR_BUSCTL3 (0x08)
#define MCF_GPIO_PODR_BUSCTL_PODR_BUSCTL4 (0x10)
#define MCF_GPIO_PODR_BUSCTL_PODR_BUSCTL5 (0x20)
#define MCF_GPIO_PODR_BUSCTL_PODR_BUSCTL6 (0x40)
#define MCF_GPIO_PODR_BUSCTL_PODR_BUSCTL7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PODR_BS */
#define MCF_GPIO_PODR_BS_PODR_BS0 (0x01)
#define MCF_GPIO_PODR_BS_PODR_BS1 (0x02)
#define MCF_GPIO_PODR_BS_PODR_BS2 (0x04)
#define MCF_GPIO_PODR_BS_PODR_BS3 (0x08)
/* Bit definitions and macros for MCF_GPIO_PODR_CS */
#define MCF_GPIO_PODR_CS_PODR_CS1 (0x02)
#define MCF_GPIO_PODR_CS_PODR_CS2 (0x04)
#define MCF_GPIO_PODR_CS_PODR_CS3 (0x08)
#define MCF_GPIO_PODR_CS_PODR_CS4 (0x10)
#define MCF_GPIO_PODR_CS_PODR_CS5 (0x20)
#define MCF_GPIO_PODR_CS_PODR_CS6 (0x40)
#define MCF_GPIO_PODR_CS_PODR_CS7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PODR_SDRAM */
#define MCF_GPIO_PODR_SDRAM_PODR_SDRAM0 (0x01)
#define MCF_GPIO_PODR_SDRAM_PODR_SDRAM1 (0x02)
#define MCF_GPIO_PODR_SDRAM_PODR_SDRAM2 (0x04)
#define MCF_GPIO_PODR_SDRAM_PODR_SDRAM3 (0x08)
#define MCF_GPIO_PODR_SDRAM_PODR_SDRAM4 (0x10)
#define MCF_GPIO_PODR_SDRAM_PODR_SDRAM5 (0x20)
/* Bit definitions and macros for MCF_GPIO_PODR_FECI2C */
#define MCF_GPIO_PODR_FECI2C_PODR_FECI2C0 (0x01)
#define MCF_GPIO_PODR_FECI2C_PODR_FECI2C1 (0x02)
#define MCF_GPIO_PODR_FECI2C_PODR_FECI2C2 (0x04)
#define MCF_GPIO_PODR_FECI2C_PODR_FECI2C3 (0x08)
/* Bit definitions and macros for MCF_GPIO_PODR_UARTH */
#define MCF_GPIO_PODR_UARTH_PODR_UARTH0 (0x01)
#define MCF_GPIO_PODR_UARTH_PODR_UARTH1 (0x02)
/* Bit definitions and macros for MCF_GPIO_PODR_UARTL */
#define MCF_GPIO_PODR_UARTL_PODR_UARTL0 (0x01)
#define MCF_GPIO_PODR_UARTL_PODR_UARTL1 (0x02)
#define MCF_GPIO_PODR_UARTL_PODR_UARTL2 (0x04)
#define MCF_GPIO_PODR_UARTL_PODR_UARTL3 (0x08)
#define MCF_GPIO_PODR_UARTL_PODR_UARTL4 (0x10)
#define MCF_GPIO_PODR_UARTL_PODR_UARTL5 (0x20)
#define MCF_GPIO_PODR_UARTL_PODR_UARTL6 (0x40)
#define MCF_GPIO_PODR_UARTL_PODR_UARTL7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PODR_QSPI */
#define MCF_GPIO_PODR_QSPI_PODR_QSPI0 (0x01)
#define MCF_GPIO_PODR_QSPI_PODR_QSPI1 (0x02)
#define MCF_GPIO_PODR_QSPI_PODR_QSPI2 (0x04)
#define MCF_GPIO_PODR_QSPI_PODR_QSPI3 (0x08)
#define MCF_GPIO_PODR_QSPI_PODR_QSPI4 (0x10)
/* Bit definitions and macros for MCF_GPIO_PODR_TIMER */
#define MCF_GPIO_PODR_TIMER_PODR_TIMER0 (0x01)
#define MCF_GPIO_PODR_TIMER_PODR_TIMER1 (0x02)
#define MCF_GPIO_PODR_TIMER_PODR_TIMER2 (0x04)
#define MCF_GPIO_PODR_TIMER_PODR_TIMER3 (0x08)
#define MCF_GPIO_PODR_TIMER_PODR_TIMER4 (0x10)
#define MCF_GPIO_PODR_TIMER_PODR_TIMER5 (0x20)
#define MCF_GPIO_PODR_TIMER_PODR_TIMER6 (0x40)
#define MCF_GPIO_PODR_TIMER_PODR_TIMER7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PODR_ETPU */
#define MCF_GPIO_PODR_ETPU_PODR_ETPU0 (0x01)
#define MCF_GPIO_PODR_ETPU_PODR_ETPU1 (0x02)
#define MCF_GPIO_PODR_ETPU_PODR_ETPU2 (0x04)
/* Bit definitions and macros for MCF_GPIO_PDDR_APDDR */
#define MCF_GPIO_PDDR_APDDR_PDDR_APDDR5 (0x20)
#define MCF_GPIO_PDDR_APDDR_PDDR_APDDR6 (0x40)
#define MCF_GPIO_PDDR_APDDR_PDDR_APDDR7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PDDR_DATAH */
#define MCF_GPIO_PDDR_DATAH_PDDR_DATAH0 (0x01)
#define MCF_GPIO_PDDR_DATAH_PDDR_DATAH1 (0x02)
#define MCF_GPIO_PDDR_DATAH_PDDR_DATAH2 (0x04)
#define MCF_GPIO_PDDR_DATAH_PDDR_DATAH3 (0x08)
#define MCF_GPIO_PDDR_DATAH_PDDR_DATAH4 (0x10)
#define MCF_GPIO_PDDR_DATAH_PDDR_DATAH5 (0x20)
#define MCF_GPIO_PDDR_DATAH_PDDR_DATAH6 (0x40)
#define MCF_GPIO_PDDR_DATAH_PDDR_DATAH7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PDDR_DATAL */
#define MCF_GPIO_PDDR_DATAL_PDDR_DATAL0 (0x01)
#define MCF_GPIO_PDDR_DATAL_PDDR_DATAL1 (0x02)
#define MCF_GPIO_PDDR_DATAL_PDDR_DATAL2 (0x04)
#define MCF_GPIO_PDDR_DATAL_PDDR_DATAL3 (0x08)
#define MCF_GPIO_PDDR_DATAL_PDDR_DATAL4 (0x10)
#define MCF_GPIO_PDDR_DATAL_PDDR_DATAL5 (0x20)
#define MCF_GPIO_PDDR_DATAL_PDDR_DATAL6 (0x40)
#define MCF_GPIO_PDDR_DATAL_PDDR_DATAL7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PDDR_BUSCTL */
#define MCF_GPIO_PDDR_BUSCTL_PDDR_BUSCTL0 (0x01)
#define MCF_GPIO_PDDR_BUSCTL_PDDR_BUSCTL1 (0x02)
#define MCF_GPIO_PDDR_BUSCTL_PDDR_BUSCTL2 (0x04)
#define MCF_GPIO_PDDR_BUSCTL_PDDR_BUSCTL3 (0x08)
#define MCF_GPIO_PDDR_BUSCTL_PDDR_BUSCTL4 (0x10)
#define MCF_GPIO_PDDR_BUSCTL_PDDR_BUSCTL5 (0x20)
#define MCF_GPIO_PDDR_BUSCTL_PDDR_BUSCTL6 (0x40)
#define MCF_GPIO_PDDR_BUSCTL_PDDR_BUSCTL7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PDDR_BS */
#define MCF_GPIO_PDDR_BS_PDDR_BS0 (0x01)
#define MCF_GPIO_PDDR_BS_PDDR_BS3(x) (((x)&0x07)<<1)
/* Bit definitions and macros for MCF_GPIO_PDDR_CS */
#define MCF_GPIO_PDDR_CS_PDDR_CS1 (0x02)
#define MCF_GPIO_PDDR_CS_PDDR_CS2 (0x04)
#define MCF_GPIO_PDDR_CS_PDDR_CS3 (0x08)
#define MCF_GPIO_PDDR_CS_PDDR_CS4 (0x10)
#define MCF_GPIO_PDDR_CS_PDDR_CS5 (0x20)
#define MCF_GPIO_PDDR_CS_PDDR_CS6 (0x40)
#define MCF_GPIO_PDDR_CS_PDDR_CS7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PDDR_SDRAM */
#define MCF_GPIO_PDDR_SDRAM_PDDR_SDRAM0 (0x01)
#define MCF_GPIO_PDDR_SDRAM_PDDR_SDRAM1 (0x02)
#define MCF_GPIO_PDDR_SDRAM_PDDR_SDRAM2 (0x04)
#define MCF_GPIO_PDDR_SDRAM_PDDR_SDRAM3 (0x08)
#define MCF_GPIO_PDDR_SDRAM_PDDR_SDRAM4 (0x10)
#define MCF_GPIO_PDDR_SDRAM_PDDR_SDRAM5 (0x20)
/* Bit definitions and macros for MCF_GPIO_PDDR_FECI2C */
#define MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C0 (0x01)
#define MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C1 (0x02)
#define MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C2 (0x04)
#define MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C3 (0x08)
/* Bit definitions and macros for MCF_GPIO_PDDR_UARTH */
#define MCF_GPIO_PDDR_UARTH_PDDR_UARTH0 (0x01)
#define MCF_GPIO_PDDR_UARTH_PDDR_UARTH1 (0x02)
/* Bit definitions and macros for MCF_GPIO_PDDR_UARTL */
#define MCF_GPIO_PDDR_UARTL_PDDR_UARTL0 (0x01)
#define MCF_GPIO_PDDR_UARTL_PDDR_UARTL1 (0x02)
#define MCF_GPIO_PDDR_UARTL_PDDR_UARTL2 (0x04)
#define MCF_GPIO_PDDR_UARTL_PDDR_UARTL3 (0x08)
#define MCF_GPIO_PDDR_UARTL_PDDR_UARTL4 (0x10)
#define MCF_GPIO_PDDR_UARTL_PDDR_UARTL5 (0x20)
#define MCF_GPIO_PDDR_UARTL_PDDR_UARTL6 (0x40)
#define MCF_GPIO_PDDR_UARTL_PDDR_UARTL7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PDDR_QSPI */
#define MCF_GPIO_PDDR_QSPI_PDDR_QSPI0 (0x01)
#define MCF_GPIO_PDDR_QSPI_PDDR_QSPI1 (0x02)
#define MCF_GPIO_PDDR_QSPI_PDDR_QSPI2 (0x04)
#define MCF_GPIO_PDDR_QSPI_PDDR_QSPI3 (0x08)
#define MCF_GPIO_PDDR_QSPI_PDDR_QSPI4 (0x10)
/* Bit definitions and macros for MCF_GPIO_PDDR_TIMER */
#define MCF_GPIO_PDDR_TIMER_PDDR_TIMER0 (0x01)
#define MCF_GPIO_PDDR_TIMER_PDDR_TIMER1 (0x02)
#define MCF_GPIO_PDDR_TIMER_PDDR_TIMER2 (0x04)
#define MCF_GPIO_PDDR_TIMER_PDDR_TIMER3 (0x08)
#define MCF_GPIO_PDDR_TIMER_PDDR_TIMER4 (0x10)
#define MCF_GPIO_PDDR_TIMER_PDDR_TIMER5 (0x20)
#define MCF_GPIO_PDDR_TIMER_PDDR_TIMER6 (0x40)
#define MCF_GPIO_PDDR_TIMER_PDDR_TIMER7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PDDR_ETPU */
#define MCF_GPIO_PDDR_ETPU_PDDR_ETPU0 (0x01)
#define MCF_GPIO_PDDR_ETPU_PDDR_ETPU1 (0x02)
#define MCF_GPIO_PDDR_ETPU_PDDR_ETPU2 (0x04)
/* Bit definitions and macros for MCF_GPIO_PPDSDR_ADDR */
#define MCF_GPIO_PPDSDR_ADDR_PPDSDR_ADDR5 (0x20)
#define MCF_GPIO_PPDSDR_ADDR_PPDSDR_ADDR6 (0x40)
#define MCF_GPIO_PPDSDR_ADDR_PPDSDR_ADDR7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PPDSDR_DATAH */
#define MCF_GPIO_PPDSDR_DATAH_PPDSDR_DATAH0 (0x01)
#define MCF_GPIO_PPDSDR_DATAH_PPDSDR_DATAH1 (0x02)
#define MCF_GPIO_PPDSDR_DATAH_PPDSDR_DATAH2 (0x04)
#define MCF_GPIO_PPDSDR_DATAH_PPDSDR_DATAH3 (0x08)
#define MCF_GPIO_PPDSDR_DATAH_PPDSDR_DATAH4 (0x10)
#define MCF_GPIO_PPDSDR_DATAH_PPDSDR_DATAH5 (0x20)
#define MCF_GPIO_PPDSDR_DATAH_PPDSDR_DATAH6 (0x40)
#define MCF_GPIO_PPDSDR_DATAH_PPDSDR_DATAH7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PPDSDR_DATAL */
#define MCF_GPIO_PPDSDR_DATAL_PPDSDR_DATAL0 (0x01)
#define MCF_GPIO_PPDSDR_DATAL_PPDSDR_DATAL1 (0x02)
#define MCF_GPIO_PPDSDR_DATAL_PPDSDR_DATAL2 (0x04)
#define MCF_GPIO_PPDSDR_DATAL_PPDSDR_DATAL3 (0x08)
#define MCF_GPIO_PPDSDR_DATAL_PPDSDR_DATAL4 (0x10)
#define MCF_GPIO_PPDSDR_DATAL_PPDSDR_DATAL5 (0x20)
#define MCF_GPIO_PPDSDR_DATAL_PPDSDR_DATAL6 (0x40)
#define MCF_GPIO_PPDSDR_DATAL_PPDSDR_DATAL7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PPDSDR_BUSCTL */
#define MCF_GPIO_PPDSDR_BUSCTL_PPDSDR_BUSCTL0 (0x01)
#define MCF_GPIO_PPDSDR_BUSCTL_PPDSDR_BUSCTL1 (0x02)
#define MCF_GPIO_PPDSDR_BUSCTL_PPDSDR_BUSCTL2 (0x04)
#define MCF_GPIO_PPDSDR_BUSCTL_PPDSDR_BUSCTL3 (0x08)
#define MCF_GPIO_PPDSDR_BUSCTL_PPDSDR_BUSCTL4 (0x10)
#define MCF_GPIO_PPDSDR_BUSCTL_PPDSDR_BUSCTL5 (0x20)
#define MCF_GPIO_PPDSDR_BUSCTL_PPDSDR_BUSCTL6 (0x40)
#define MCF_GPIO_PPDSDR_BUSCTL_PPDSDR_BUSCTL7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PPDSDR_BS */
#define MCF_GPIO_PPDSDR_BS_PPDSDR_BS0 (0x01)
#define MCF_GPIO_PPDSDR_BS_PPDSDR_BS1 (0x02)
#define MCF_GPIO_PPDSDR_BS_PPDSDR_BS2 (0x04)
#define MCF_GPIO_PPDSDR_BS_PPDSDR_BS3 (0x08)
/* Bit definitions and macros for MCF_GPIO_PPDSDR_FECI2C */
#define MCF_GPIO_PPDSDR_FECI2C_PPDSDR_FECI2C0 (0x01)
#define MCF_GPIO_PPDSDR_FECI2C_PPDSDR_FECI2C1 (0x02)
#define MCF_GPIO_PPDSDR_FECI2C_PPDSDR_FECI2C2 (0x04)
#define MCF_GPIO_PPDSDR_FECI2C_PPDSDR_FECI2C3 (0x08)
/* Bit definitions and macros for MCF_GPIO_PPDSDR_CS */
#define MCF_GPIO_PPDSDR_CS_PPDSDR_CS1 (0x02)
#define MCF_GPIO_PPDSDR_CS_PPDSDR_CS2 (0x04)
#define MCF_GPIO_PPDSDR_CS_PPDSDR_CS3 (0x08)
#define MCF_GPIO_PPDSDR_CS_PPDSDR_CS4 (0x10)
#define MCF_GPIO_PPDSDR_CS_PPDSDR_CS5 (0x20)
#define MCF_GPIO_PPDSDR_CS_PPDSDR_CS6 (0x40)
#define MCF_GPIO_PPDSDR_CS_PPDSDR_CS7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PPDSDR_SDRAM */
#define MCF_GPIO_PPDSDR_SDRAM_PPDSDR_SDRAM0 (0x01)
#define MCF_GPIO_PPDSDR_SDRAM_PPDSDR_SDRAM1 (0x02)
#define MCF_GPIO_PPDSDR_SDRAM_PPDSDR_SDRAM2 (0x04)
#define MCF_GPIO_PPDSDR_SDRAM_PPDSDR_SDRAM3 (0x08)
#define MCF_GPIO_PPDSDR_SDRAM_PPDSDR_SDRAM4 (0x10)
#define MCF_GPIO_PPDSDR_SDRAM_PPDSDR_SDRAM5 (0x20)
#define MCF_GPIO_PPDSDR_SDRAM_PPDSDR_SDRAM6 (0x40)
#define MCF_GPIO_PPDSDR_SDRAM_PPDSDR_SDRAM7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PPDSDR_UARTH */
#define MCF_GPIO_PPDSDR_UARTH_PPDSDR_UARTH0 (0x01)
#define MCF_GPIO_PPDSDR_UARTH_PPDSDR_UARTH1 (0x02)
/* Bit definitions and macros for MCF_GPIO_PPDSDR_UARTL */
#define MCF_GPIO_PPDSDR_UARTL_PPDSDR_UARTL0 (0x01)
#define MCF_GPIO_PPDSDR_UARTL_PPDSDR_UARTL1 (0x02)
#define MCF_GPIO_PPDSDR_UARTL_PPDSDR_UARTL2 (0x04)
#define MCF_GPIO_PPDSDR_UARTL_PPDSDR_UARTL3 (0x08)
#define MCF_GPIO_PPDSDR_UARTL_PPDSDR_UARTL4 (0x10)
#define MCF_GPIO_PPDSDR_UARTL_PPDSDR_UARTL5 (0x20)
#define MCF_GPIO_PPDSDR_UARTL_PPDSDR_UARTL6 (0x40)
#define MCF_GPIO_PPDSDR_UARTL_PPDSDR_UARTL7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PPDSDR_QSPI */
#define MCF_GPIO_PPDSDR_QSPI_PPDSDR_QSPI0 (0x01)
#define MCF_GPIO_PPDSDR_QSPI_PPDSDR_QSPI1 (0x02)
#define MCF_GPIO_PPDSDR_QSPI_PPDSDR_QSPI2 (0x04)
#define MCF_GPIO_PPDSDR_QSPI_PPDSDR_QSPI3 (0x08)
#define MCF_GPIO_PPDSDR_QSPI_PPDSDR_QSPI4 (0x10)
/* Bit definitions and macros for MCF_GPIO_PPDSDR_TIMER */
#define MCF_GPIO_PPDSDR_TIMER_PPDSDR_TIMER0 (0x01)
#define MCF_GPIO_PPDSDR_TIMER_PPDSDR_TIMER1 (0x02)
#define MCF_GPIO_PPDSDR_TIMER_PPDSDR_TIMER2 (0x04)
#define MCF_GPIO_PPDSDR_TIMER_PPDSDR_TIMER3 (0x08)
#define MCF_GPIO_PPDSDR_TIMER_PPDSDR_TIMER4 (0x10)
#define MCF_GPIO_PPDSDR_TIMER_PPDSDR_TIMER5 (0x20)
#define MCF_GPIO_PPDSDR_TIMER_PPDSDR_TIMER6 (0x40)
#define MCF_GPIO_PPDSDR_TIMER_PPDSDR_TIMER7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PPDSDR_ETPU */
#define MCF_GPIO_PPDSDR_ETPU_PPDSDR_ETPU0 (0x01)
#define MCF_GPIO_PPDSDR_ETPU_PPDSDR_ETPU1 (0x02)
#define MCF_GPIO_PPDSDR_ETPU_PPDSDR_ETPU2 (0x04)
/* Bit definitions and macros for MCF_GPIO_PCLRR_ADDR */
#define MCF_GPIO_PCLRR_ADDR_PCLRR_ADDR5 (0x20)
#define MCF_GPIO_PCLRR_ADDR_PCLRR_ADDR6 (0x40)
#define MCF_GPIO_PCLRR_ADDR_PCLRR_ADDR7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PCLRR_DATAH */
#define MCF_GPIO_PCLRR_DATAH_PCLRR_DATAH0 (0x01)
#define MCF_GPIO_PCLRR_DATAH_PCLRR_DATAH1 (0x02)
#define MCF_GPIO_PCLRR_DATAH_PCLRR_DATAH2 (0x04)
#define MCF_GPIO_PCLRR_DATAH_PCLRR_DATAH3 (0x08)
#define MCF_GPIO_PCLRR_DATAH_PCLRR_DATAH4 (0x10)
#define MCF_GPIO_PCLRR_DATAH_PCLRR_DATAH5 (0x20)
#define MCF_GPIO_PCLRR_DATAH_PCLRR_DATAH6 (0x40)
#define MCF_GPIO_PCLRR_DATAH_PCLRR_DATAH7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PCLRR_DATAL */
#define MCF_GPIO_PCLRR_DATAL_PCLRR_DATAL0 (0x01)
#define MCF_GPIO_PCLRR_DATAL_PCLRR_DATAL1 (0x02)
#define MCF_GPIO_PCLRR_DATAL_PCLRR_DATAL2 (0x04)
#define MCF_GPIO_PCLRR_DATAL_PCLRR_DATAL3 (0x08)
#define MCF_GPIO_PCLRR_DATAL_PCLRR_DATAL4 (0x10)
#define MCF_GPIO_PCLRR_DATAL_PCLRR_DATAL5 (0x20)
#define MCF_GPIO_PCLRR_DATAL_PCLRR_DATAL6 (0x40)
#define MCF_GPIO_PCLRR_DATAL_PCLRR_DATAL7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PCLRR_BUSCTL */
#define MCF_GPIO_PCLRR_BUSCTL_PCLRR_BUSCTL0 (0x01)
#define MCF_GPIO_PCLRR_BUSCTL_PCLRR_BUSCTL1 (0x02)
#define MCF_GPIO_PCLRR_BUSCTL_PCLRR_BUSCTL2 (0x04)
#define MCF_GPIO_PCLRR_BUSCTL_PCLRR_BUSCTL3 (0x08)
#define MCF_GPIO_PCLRR_BUSCTL_PCLRR_BUSCTL4 (0x10)
#define MCF_GPIO_PCLRR_BUSCTL_PCLRR_BUSCTL5 (0x20)
#define MCF_GPIO_PCLRR_BUSCTL_PCLRR_BUSCTL6 (0x40)
#define MCF_GPIO_PCLRR_BUSCTL_PCLRR_BUSCTL7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PCLRR_BS */
#define MCF_GPIO_PCLRR_BS_PCLRR_BS0 (0x01)
#define MCF_GPIO_PCLRR_BS_PCLRR_BS1 (0x02)
#define MCF_GPIO_PCLRR_BS_PCLRR_BS2 (0x04)
#define MCF_GPIO_PCLRR_BS_PCLRR_BS3 (0x08)
/* Bit definitions and macros for MCF_GPIO_PCLRR_CS */
#define MCF_GPIO_PCLRR_CS_PCLRR_CS1 (0x02)
#define MCF_GPIO_PCLRR_CS_PCLRR_CS2 (0x04)
#define MCF_GPIO_PCLRR_CS_PCLRR_CS3 (0x08)
#define MCF_GPIO_PCLRR_CS_PCLRR_CS4 (0x10)
#define MCF_GPIO_PCLRR_CS_PCLRR_CS5 (0x20)
#define MCF_GPIO_PCLRR_CS_PCLRR_CS6 (0x40)
#define MCF_GPIO_PCLRR_CS_PCLRR_CS7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PCLRR_SDRAM */
#define MCF_GPIO_PCLRR_SDRAM_PCLRR_SDRAM0 (0x01)
#define MCF_GPIO_PCLRR_SDRAM_PCLRR_SDRAM1 (0x02)
#define MCF_GPIO_PCLRR_SDRAM_PCLRR_SDRAM2 (0x04)
#define MCF_GPIO_PCLRR_SDRAM_PCLRR_SDRAM3 (0x08)
#define MCF_GPIO_PCLRR_SDRAM_PCLRR_SDRAM4 (0x10)
#define MCF_GPIO_PCLRR_SDRAM_PCLRR_SDRAM5 (0x20)
/* Bit definitions and macros for MCF_GPIO_PCLRR_FECI2C */
#define MCF_GPIO_PCLRR_FECI2C_PCLRR_FECI2C0 (0x01)
#define MCF_GPIO_PCLRR_FECI2C_PCLRR_FECI2C1 (0x02)
#define MCF_GPIO_PCLRR_FECI2C_PCLRR_FECI2C2 (0x04)
#define MCF_GPIO_PCLRR_FECI2C_PCLRR_FECI2C3 (0x08)
/* Bit definitions and macros for MCF_GPIO_PCLRR_UARTH */
#define MCF_GPIO_PCLRR_UARTH_PCLRR_UARTH0 (0x01)
#define MCF_GPIO_PCLRR_UARTH_PCLRR_UARTH1 (0x02)
/* Bit definitions and macros for MCF_GPIO_PCLRR_UARTL */
#define MCF_GPIO_PCLRR_UARTL_PCLRR_UARTL0 (0x01)
#define MCF_GPIO_PCLRR_UARTL_PCLRR_UARTL1 (0x02)
#define MCF_GPIO_PCLRR_UARTL_PCLRR_UARTL2 (0x04)
#define MCF_GPIO_PCLRR_UARTL_PCLRR_UARTL3 (0x08)
#define MCF_GPIO_PCLRR_UARTL_PCLRR_UARTL4 (0x10)
#define MCF_GPIO_PCLRR_UARTL_PCLRR_UARTL5 (0x20)
#define MCF_GPIO_PCLRR_UARTL_PCLRR_UARTL6 (0x40)
#define MCF_GPIO_PCLRR_UARTL_PCLRR_UARTL7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PCLRR_QSPI */
#define MCF_GPIO_PCLRR_QSPI_PCLRR_QSPI0 (0x01)
#define MCF_GPIO_PCLRR_QSPI_PCLRR_QSPI1 (0x02)
#define MCF_GPIO_PCLRR_QSPI_PCLRR_QSPI2 (0x04)
#define MCF_GPIO_PCLRR_QSPI_PCLRR_QSPI3 (0x08)
#define MCF_GPIO_PCLRR_QSPI_PCLRR_QSPI4 (0x10)
/* Bit definitions and macros for MCF_GPIO_PCLRR_TIMER */
#define MCF_GPIO_PCLRR_TIMER_PCLRR_TIMER0 (0x01)
#define MCF_GPIO_PCLRR_TIMER_PCLRR_TIMER1 (0x02)
#define MCF_GPIO_PCLRR_TIMER_PCLRR_TIMER2 (0x04)
#define MCF_GPIO_PCLRR_TIMER_PCLRR_TIMER3 (0x08)
#define MCF_GPIO_PCLRR_TIMER_PCLRR_TIMER4 (0x10)
#define MCF_GPIO_PCLRR_TIMER_PCLRR_TIMER5 (0x20)
#define MCF_GPIO_PCLRR_TIMER_PCLRR_TIMER6 (0x40)
#define MCF_GPIO_PCLRR_TIMER_PCLRR_TIMER7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PCLRR_ETPU */
#define MCF_GPIO_PCLRR_ETPU_PCLRR_ETPU0 (0x01)
#define MCF_GPIO_PCLRR_ETPU_PCLRR_ETPU1 (0x02)
#define MCF_GPIO_PCLRR_ETPU_PCLRR_ETPU2 (0x04)
/* Bit definitions and macros for MCF_GPIO_PAR_AD */
#define MCF_GPIO_PAR_AD_PAR_DATAL (0x01)
#define MCF_GPIO_PAR_AD_PAR_ADDR21 (0x20)
#define MCF_GPIO_PAR_AD_PAR_ADDR22 (0x40)
#define MCF_GPIO_PAR_AD_PAR_ADDR23 (0x80)
/* Bit definitions and macros for MCF_GPIO_PAR_BUSCTL */
#define MCF_GPIO_PAR_BUSCTL_PAR_TIP(x) (((x)&0x0003)<<0)
#define MCF_GPIO_PAR_BUSCTL_PAR_TS(x) (((x)&0x0003)<<2)
#define MCF_GPIO_PAR_BUSCTL_PAR_TSIZ0 (0x0010)
#define MCF_GPIO_PAR_BUSCTL_PAR_TSIZ1 (0x0040)
#define MCF_GPIO_PAR_BUSCTL_PAR_RWB (0x0100)
#define MCF_GPIO_PAR_BUSCTL_PAR_TEA(x) (((x)&0x0003)<<10)
#define MCF_GPIO_PAR_BUSCTL_PAR_TA (0x1000)
#define MCF_GPIO_PAR_BUSCTL_PAR_OE (0x4000)
#define MCF_GPIO_PAR_BUSCTL_PAR_TEA_GPIO (0x0000)
#define MCF_GPIO_PAR_BUSCTL_PAR_TEA_DMA (0x0800)
#define MCF_GPIO_PAR_BUSCTL_PAR_TEA_TEA (0x0C00)
#define MCF_GPIO_PAR_BUSCTL_PAR_TS_GPIO (0x0000)
#define MCF_GPIO_PAR_BUSCTL_PAR_TS_DMA (0x0080)
#define MCF_GPIO_PAR_BUSCTL_PAR_TS_TS (0x00C0)
#define MCF_GPIO_PAR_BUSCTL_PAR_TIP_GPIO (0x0000)
#define MCF_GPIO_PAR_BUSCTL_PAR_TIP_DMA (0x0002)
#define MCF_GPIO_PAR_BUSCTL_PAR_TIP_TEA (0x0003)
/* Bit definitions and macros for MCF_GPIO_PAR_BS */
#define MCF_GPIO_PAR_BS_PAR_BS0 (0x01)
#define MCF_GPIO_PAR_BS_PAR_BS1 (0x02)
#define MCF_GPIO_PAR_BS_PAR_BS2 (0x04)
#define MCF_GPIO_PAR_BS_PAR_BS3 (0x08)
/* Bit definitions and macros for MCF_GPIO_PAR_CS */
#define MCF_GPIO_PAR_CS_PAR_CS1 (0x02)
#define MCF_GPIO_PAR_CS_PAR_CS2 (0x04)
#define MCF_GPIO_PAR_CS_PAR_CS3 (0x08)
#define MCF_GPIO_PAR_CS_PAR_CS4 (0x10)
#define MCF_GPIO_PAR_CS_PAR_CS5 (0x20)
#define MCF_GPIO_PAR_CS_PAR_CS6 (0x40)
#define MCF_GPIO_PAR_CS_PAR_CS7 (0x80)
/* Bit definitions and macros for MCF_GPIO_PAR_SDRAM */
#define MCF_GPIO_PAR_SDRAM_PAR_SDCS0 (0x01)
#define MCF_GPIO_PAR_SDRAM_PAR_SDCS1 (0x02)
#define MCF_GPIO_PAR_SDRAM_PAR_SCKE (0x04)
#define MCF_GPIO_PAR_SDRAM_PAR_SRAS (0x08)
#define MCF_GPIO_PAR_SDRAM_PAR_SCAS (0x10)
#define MCF_GPIO_PAR_SDRAM_PAR_SDWE (0x20)
#define MCF_GPIO_PAR_SDRAM_PAR_CSSDCS(x) (((x)&0x03)<<6)
/* Bit definitions and macros for MCF_GPIO_PAR_FECI2C */
#define MCF_GPIO_PAR_FECI2C_PAR_SDA(x) (((x)&0x03)<<0)
#define MCF_GPIO_PAR_FECI2C_PAR_SCL(x) (((x)&0x03)<<2)
#define MCF_GPIO_PAR_FECI2C_PAR_EMDIO(x) (((x)&0x03)<<4)
#define MCF_GPIO_PAR_FECI2C_PAR_EMDC(x) (((x)&0x03)<<6)
#define MCF_GPIO_PAR_FECI2C_PAR_EMDC_GPIO (0x00)
#define MCF_GPIO_PAR_FECI2C_PAR_EMDC_UART2 (0x40)
#define MCF_GPIO_PAR_FECI2C_PAR_EMDC_I2C (0x80)
#define MCF_GPIO_PAR_FECI2C_PAR_EMDC_FEC (0xC0)
#define MCF_GPIO_PAR_FECI2C_PAR_EMDIO_GPIO (0x00)
#define MCF_GPIO_PAR_FECI2C_PAR_EMDIO_UART2 (0x10)
#define MCF_GPIO_PAR_FECI2C_PAR_EMDIO_I2C (0x20)
#define MCF_GPIO_PAR_FECI2C_PAR_EMDIO_FEC (0x30)
#define MCF_GPIO_PAR_FECI2C_PAR_SCL_GPIO (0x00)
#define MCF_GPIO_PAR_FECI2C_PAR_SCL_FLEX (0x08)
#define MCF_GPIO_PAR_FECI2C_PAR_SCL_I2C (0x0C)
#define MCF_GPIO_PAR_FECI2C_PAR_SDA_GPIO (0x00)
#define MCF_GPIO_PAR_FECI2C_PAR_SDA_FLEX (0x02)
#define MCF_GPIO_PAR_FECI2C_PAR_SDA_I2C (0x03)
/* Bit definitions and macros for MCF_GPIO_PAR_UART */
#define MCF_GPIO_PAR_UART_PAR_U0RTS (0x0001)
#define MCF_GPIO_PAR_UART_PAR_U0CTS (0x0002)
#define MCF_GPIO_PAR_UART_PAR_U0TXD (0x0004)
#define MCF_GPIO_PAR_UART_PAR_U0RXD (0x0008)
#define MCF_GPIO_PAR_UART_PAR_U1RTS(x) (((x)&0x0003)<<4)
#define MCF_GPIO_PAR_UART_PAR_U1CTS(x) (((x)&0x0003)<<6)
#define MCF_GPIO_PAR_UART_PAR_U1TXD(x) (((x)&0x0003)<<8)
#define MCF_GPIO_PAR_UART_PAR_U1RXD(x) (((x)&0x0003)<<10)
#define MCF_GPIO_PAR_UART_PAR_U2TXD (0x1000)
#define MCF_GPIO_PAR_UART_PAR_U2RXD (0x2000)
#define MCF_GPIO_PAR_UART_PAR_CAN1EN (0x4000)
#define MCF_GPIO_PAR_UART_PAR_DREQ2 (0x8000)
#define MCF_GPIO_PAR_UART_PAR_U1RXD_GPIO (0x0000)
#define MCF_GPIO_PAR_UART_PAR_U1RXD_FLEX (0x0800)
#define MCF_GPIO_PAR_UART_PAR_U1RXD_UART1 (0x0C00)
#define MCF_GPIO_PAR_UART_PAR_U1TXD_GPIO (0x0000)
#define MCF_GPIO_PAR_UART_PAR_U1TXD_FLEX (0x0200)
#define MCF_GPIO_PAR_UART_PAR_U1TXD_UART1 (0x0300)
#define MCF_GPIO_PAR_UART_PAR_U1CTS_GPIO (0x0000)
#define MCF_GPIO_PAR_UART_PAR_U1CTS_UART2 (0x0080)
#define MCF_GPIO_PAR_UART_PAR_U1CTS_UART1 (0x00C0)
#define MCF_GPIO_PAR_UART_PAR_U1RTS_GPIO (0x0000)
#define MCF_GPIO_PAR_UART_PAR_U1RTS_UART2 (0x0020)
#define MCF_GPIO_PAR_UART_PAR_U1RTS_UART1 (0x0030)
/* Bit definitions and macros for MCF_GPIO_PAR_QSPI */
#define MCF_GPIO_PAR_QSPI_PAR_SCK(x) (((x)&0x03)<<0)
#define MCF_GPIO_PAR_QSPI_PAR_DOUT (0x04)
#define MCF_GPIO_PAR_QSPI_PAR_DIN(x) (((x)&0x03)<<3)
#define MCF_GPIO_PAR_QSPI_PAR_PCS0 (0x20)
#define MCF_GPIO_PAR_QSPI_PAR_PCS1(x) (((x)&0x03)<<6)
#define MCF_GPIO_PAR_QSPI_PAR_PCS1_GPIO (0x00)
#define MCF_GPIO_PAR_QSPI_PAR_PCS1_SDRAMC (0x80)
#define MCF_GPIO_PAR_QSPI_PAR_PCS1_QSPI (0xC0)
#define MCF_GPIO_PAR_QSPI_PAR_DIN_GPIO (0x00)
#define MCF_GPIO_PAR_QSPI_PAR_DIN_I2C (0x10)
#define MCF_GPIO_PAR_QSPI_PAR_DIN_QSPI (0x1C)
#define MCF_GPIO_PAR_QSPI_PAR_SCK_GPIO (0x00)
#define MCF_GPIO_PAR_QSPI_PAR_SCK_I2C (0x02)
#define MCF_GPIO_PAR_QSPI_PAR_SCK_QSPI (0x03)
/* Bit definitions and macros for MCF_GPIO_PAR_TIMER */
#define MCF_GPIO_PAR_TIMER_PAR_T0OUT(x) (((x)&0x0003)<<0)
#define MCF_GPIO_PAR_TIMER_PAR_T1OUT(x) (((x)&0x0003)<<2)
#define MCF_GPIO_PAR_TIMER_PAR_T2OUT(x) (((x)&0x0003)<<4)
#define MCF_GPIO_PAR_TIMER_PAR_T3OUT(x) (((x)&0x0003)<<6)
#define MCF_GPIO_PAR_TIMER_PAR_T0IN(x) (((x)&0x0003)<<8)
#define MCF_GPIO_PAR_TIMER_PAR_T1IN(x) (((x)&0x0003)<<10)
#define MCF_GPIO_PAR_TIMER_PAR_T2IN(x) (((x)&0x0003)<<12)
#define MCF_GPIO_PAR_TIMER_PAR_T3IN(x) (((x)&0x0003)<<14)
#define MCF_GPIO_PAR_TIMER_PAR_T3IN_GPIO (0x0000)
#define MCF_GPIO_PAR_TIMER_PAR_T3IN_QSPI (0x4000)
#define MCF_GPIO_PAR_TIMER_PAR_T3IN_UART2 (0x8000)
#define MCF_GPIO_PAR_TIMER_PAR_T3IN_T3IN (0xC000)
#define MCF_GPIO_PAR_TIMER_PAR_T2IN_GPIO (0x0000)
#define MCF_GPIO_PAR_TIMER_PAR_T2IN_T2OUT (0x1000)
#define MCF_GPIO_PAR_TIMER_PAR_T2IN_DMA (0x2000)
#define MCF_GPIO_PAR_TIMER_PAR_T2IN_T2IN (0x3000)
#define MCF_GPIO_PAR_TIMER_PAR_T1IN_GPIO (0x0000)
#define MCF_GPIO_PAR_TIMER_PAR_T1IN_T1OUT (0x0400)
#define MCF_GPIO_PAR_TIMER_PAR_T1IN_DMA (0x0800)
#define MCF_GPIO_PAR_TIMER_PAR_T1IN_T1IN (0x0C00)
#define MCF_GPIO_PAR_TIMER_PAR_T0IN_GPIO (0x0000)
#define MCF_GPIO_PAR_TIMER_PAR_T0IN_DMA (0x0200)
#define MCF_GPIO_PAR_TIMER_PAR_T0IN_T0IN (0x0300)
#define MCF_GPIO_PAR_TIMER_PAR_T3OUT_GPIO (0x0000)
#define MCF_GPIO_PAR_TIMER_PAR_T3OUT_QSPI (0x0040)
#define MCF_GPIO_PAR_TIMER_PAR_T3OUT_UART2 (0x0080)
#define MCF_GPIO_PAR_TIMER_PAR_T3OUT_T3OUT (0x00C0)
#define MCF_GPIO_PAR_TIMER_PAR_T2OUT_GPIO (0x0000)
#define MCF_GPIO_PAR_TIMER_PAR_T2OUT_DMA (0x0020)
#define MCF_GPIO_PAR_TIMER_PAR_T2OUT_T2OUT (0x0030)
#define MCF_GPIO_PAR_TIMER_PAR_T1OUT_GPIO (0x0000)
#define MCF_GPIO_PAR_TIMER_PAR_T1OUT_DMA (0x0008)
#define MCF_GPIO_PAR_TIMER_PAR_T1OUT_T1OUT (0x000C)
#define MCF_GPIO_PAR_TIMER_PAR_T0OUT_GPIO (0x0000)
#define MCF_GPIO_PAR_TIMER_PAR_T0OUT_DMA (0x0002)
#define MCF_GPIO_PAR_TIMER_PAR_T0OUT_T0OUT (0x0003)
/* Bit definitions and macros for MCF_GPIO_PAR_ETPU */
#define MCF_GPIO_PAR_ETPU_PAR_LTPU_ODIS (0x01)
#define MCF_GPIO_PAR_ETPU_PAR_UTPU_ODIS (0x02)
#define MCF_GPIO_PAR_ETPU_PAR_TCRCLK (0x04)
/* Bit definitions and macros for MCF_GPIO_DSCR_EIM */
#define MCF_GPIO_DSCR_EIM_DSCR_EIM0 (0x01)
#define MCF_GPIO_DSCR_EIM_DSCR_EIM1 (0x10)
/* Bit definitions and macros for MCF_GPIO_DSCR_ETPU */
#define MCF_GPIO_DSCR_ETPU_DSCR_ETPU_7_0 (0x01)
#define MCF_GPIO_DSCR_ETPU_DSCR_ETPU_15_8 (0x04)
#define MCF_GPIO_DSCR_ETPU_DSCR_ETPU_23_16 (0x10)
#define MCF_GPIO_DSCR_ETPU_DSCR_ETPU_31_24 (0x40)
/* Bit definitions and macros for MCF_GPIO_DSCR_FECI2C */
#define MCF_GPIO_DSCR_FECI2C_DSCR_I2C (0x01)
#define MCF_GPIO_DSCR_FECI2C_DSCR_FEC (0x10)
/* Bit definitions and macros for MCF_GPIO_DSCR_UART */
#define MCF_GPIO_DSCR_UART_DSCR_UART0 (0x01)
#define MCF_GPIO_DSCR_UART_DSCR_UART1 (0x04)
#define MCF_GPIO_DSCR_UART_DSCR_UART2 (0x10)
#define MCF_GPIO_DSCR_UART_DSCR_IRQ (0x40)
/* Bit definitions and macros for MCF_GPIO_DSCR_QSPI */
#define MCF_GPIO_DSCR_QSPI_DSCR_QSPI (0x01)
/* Bit definitions and macros for MCF_GPIO_DSCR_TIMER */
#define MCF_GPIO_DSCR_TIMER_DSCR_TIMER (0x01)
/********************************************************************/
#endif /* __MCF523X_GPIO_H__ */

View File

@@ -0,0 +1,57 @@
/*
* File: mcf523x_i2c.h
* Purpose: Register and bit definitions for the MCF523X
*
* Notes:
*
*/
#ifndef __MCF523X_I2C_H__
#define __MCF523X_I2C_H__
/*********************************************************************
*
* I2C Module (I2C)
*
*********************************************************************/
/* Register read/write macros */
#define MCF_I2C_I2AR (*(vuint8 *)(void*)(&__IPSBAR[0x000300]))
#define MCF_I2C_I2FDR (*(vuint8 *)(void*)(&__IPSBAR[0x000304]))
#define MCF_I2C_I2CR (*(vuint8 *)(void*)(&__IPSBAR[0x000308]))
#define MCF_I2C_I2SR (*(vuint8 *)(void*)(&__IPSBAR[0x00030C]))
#define MCF_I2C_I2DR (*(vuint8 *)(void*)(&__IPSBAR[0x000310]))
#define MCF_I2C_I2ICR (*(vuint8 *)(void*)(&__IPSBAR[0x000320]))
/* Bit definitions and macros for MCF_I2C_I2AR */
#define MCF_I2C_I2AR_ADR(x) (((x)&0x7F)<<1)
/* Bit definitions and macros for MCF_I2C_I2FDR */
#define MCF_I2C_I2FDR_IC(x) (((x)&0x3F)<<0)
/* Bit definitions and macros for MCF_I2C_I2CR */
#define MCF_I2C_I2CR_RSTA (0x04)
#define MCF_I2C_I2CR_TXAK (0x08)
#define MCF_I2C_I2CR_MTX (0x10)
#define MCF_I2C_I2CR_MSTA (0x20)
#define MCF_I2C_I2CR_IIEN (0x40)
#define MCF_I2C_I2CR_IEN (0x80)
/* Bit definitions and macros for MCF_I2C_I2SR */
#define MCF_I2C_I2SR_RXAK (0x01)
#define MCF_I2C_I2SR_IIF (0x02)
#define MCF_I2C_I2SR_SRW (0x04)
#define MCF_I2C_I2SR_IAL (0x10)
#define MCF_I2C_I2SR_IBB (0x20)
#define MCF_I2C_I2SR_IAAS (0x40)
#define MCF_I2C_I2SR_ICF (0x80)
/* Bit definitions and macros for MCF_I2C_I2ICR */
#define MCF_I2C_I2ICR_IE (0x01)
#define MCF_I2C_I2ICR_RE (0x02)
#define MCF_I2C_I2ICR_TE (0x04)
#define MCF_I2C_I2ICR_BNBE (0x08)
/********************************************************************/
#endif /* __MCF523X_I2C_H__ */

View File

@@ -0,0 +1,317 @@
/*
* File: mcf523x_intc0.h
* Purpose: Register and bit definitions for the MCF523X
*
* Notes:
*
*/
#ifndef __MCF523X_INTC0_H__
#define __MCF523X_INTC0_H__
/*********************************************************************
*
* Interrupt Controller 0 (INTC0)
*
*********************************************************************/
/* Register read/write macros */
#define MCF_INTC0_IPRH (*(vuint32*)(void*)(&__IPSBAR[0x000C00]))
#define MCF_INTC0_IPRL (*(vuint32*)(void*)(&__IPSBAR[0x000C04]))
#define MCF_INTC0_IMRH (*(vuint32*)(void*)(&__IPSBAR[0x000C08]))
#define MCF_INTC0_IMRL (*(vuint32*)(void*)(&__IPSBAR[0x000C0C]))
#define MCF_INTC0_INTFRCH (*(vuint32*)(void*)(&__IPSBAR[0x000C10]))
#define MCF_INTC0_INTFRCL (*(vuint32*)(void*)(&__IPSBAR[0x000C14]))
#define MCF_INTC0_IRLR (*(vuint8 *)(void*)(&__IPSBAR[0x000C18]))
#define MCF_INTC0_IACKLPR (*(vuint8 *)(void*)(&__IPSBAR[0x000C19]))
#define MCF_INTC0_ICR0 (*(vuint8 *)(void*)(&__IPSBAR[0x000C40]))
#define MCF_INTC0_ICR1 (*(vuint8 *)(void*)(&__IPSBAR[0x000C41]))
#define MCF_INTC0_ICR2 (*(vuint8 *)(void*)(&__IPSBAR[0x000C42]))
#define MCF_INTC0_ICR3 (*(vuint8 *)(void*)(&__IPSBAR[0x000C43]))
#define MCF_INTC0_ICR4 (*(vuint8 *)(void*)(&__IPSBAR[0x000C44]))
#define MCF_INTC0_ICR5 (*(vuint8 *)(void*)(&__IPSBAR[0x000C45]))
#define MCF_INTC0_ICR6 (*(vuint8 *)(void*)(&__IPSBAR[0x000C46]))
#define MCF_INTC0_ICR7 (*(vuint8 *)(void*)(&__IPSBAR[0x000C47]))
#define MCF_INTC0_ICR8 (*(vuint8 *)(void*)(&__IPSBAR[0x000C48]))
#define MCF_INTC0_ICR9 (*(vuint8 *)(void*)(&__IPSBAR[0x000C49]))
#define MCF_INTC0_ICR10 (*(vuint8 *)(void*)(&__IPSBAR[0x000C4A]))
#define MCF_INTC0_ICR11 (*(vuint8 *)(void*)(&__IPSBAR[0x000C4B]))
#define MCF_INTC0_ICR12 (*(vuint8 *)(void*)(&__IPSBAR[0x000C4C]))
#define MCF_INTC0_ICR13 (*(vuint8 *)(void*)(&__IPSBAR[0x000C4D]))
#define MCF_INTC0_ICR14 (*(vuint8 *)(void*)(&__IPSBAR[0x000C4E]))
#define MCF_INTC0_ICR15 (*(vuint8 *)(void*)(&__IPSBAR[0x000C4F]))
#define MCF_INTC0_ICR16 (*(vuint8 *)(void*)(&__IPSBAR[0x000C50]))
#define MCF_INTC0_ICR17 (*(vuint8 *)(void*)(&__IPSBAR[0x000C51]))
#define MCF_INTC0_ICR18 (*(vuint8 *)(void*)(&__IPSBAR[0x000C52]))
#define MCF_INTC0_ICR19 (*(vuint8 *)(void*)(&__IPSBAR[0x000C53]))
#define MCF_INTC0_ICR20 (*(vuint8 *)(void*)(&__IPSBAR[0x000C54]))
#define MCF_INTC0_ICR21 (*(vuint8 *)(void*)(&__IPSBAR[0x000C55]))
#define MCF_INTC0_ICR22 (*(vuint8 *)(void*)(&__IPSBAR[0x000C56]))
#define MCF_INTC0_ICR23 (*(vuint8 *)(void*)(&__IPSBAR[0x000C57]))
#define MCF_INTC0_ICR24 (*(vuint8 *)(void*)(&__IPSBAR[0x000C58]))
#define MCF_INTC0_ICR25 (*(vuint8 *)(void*)(&__IPSBAR[0x000C59]))
#define MCF_INTC0_ICR26 (*(vuint8 *)(void*)(&__IPSBAR[0x000C5A]))
#define MCF_INTC0_ICR27 (*(vuint8 *)(void*)(&__IPSBAR[0x000C5B]))
#define MCF_INTC0_ICR28 (*(vuint8 *)(void*)(&__IPSBAR[0x000C5C]))
#define MCF_INTC0_ICR29 (*(vuint8 *)(void*)(&__IPSBAR[0x000C5D]))
#define MCF_INTC0_ICR30 (*(vuint8 *)(void*)(&__IPSBAR[0x000C5E]))
#define MCF_INTC0_ICR31 (*(vuint8 *)(void*)(&__IPSBAR[0x000C5F]))
#define MCF_INTC0_ICR32 (*(vuint8 *)(void*)(&__IPSBAR[0x000C60]))
#define MCF_INTC0_ICR33 (*(vuint8 *)(void*)(&__IPSBAR[0x000C61]))
#define MCF_INTC0_ICR34 (*(vuint8 *)(void*)(&__IPSBAR[0x000C62]))
#define MCF_INTC0_ICR35 (*(vuint8 *)(void*)(&__IPSBAR[0x000C63]))
#define MCF_INTC0_ICR36 (*(vuint8 *)(void*)(&__IPSBAR[0x000C64]))
#define MCF_INTC0_ICR37 (*(vuint8 *)(void*)(&__IPSBAR[0x000C65]))
#define MCF_INTC0_ICR38 (*(vuint8 *)(void*)(&__IPSBAR[0x000C66]))
#define MCF_INTC0_ICR39 (*(vuint8 *)(void*)(&__IPSBAR[0x000C67]))
#define MCF_INTC0_ICR40 (*(vuint8 *)(void*)(&__IPSBAR[0x000C68]))
#define MCF_INTC0_ICR41 (*(vuint8 *)(void*)(&__IPSBAR[0x000C69]))
#define MCF_INTC0_ICR42 (*(vuint8 *)(void*)(&__IPSBAR[0x000C6A]))
#define MCF_INTC0_ICR43 (*(vuint8 *)(void*)(&__IPSBAR[0x000C6B]))
#define MCF_INTC0_ICR44 (*(vuint8 *)(void*)(&__IPSBAR[0x000C6C]))
#define MCF_INTC0_ICR45 (*(vuint8 *)(void*)(&__IPSBAR[0x000C6D]))
#define MCF_INTC0_ICR46 (*(vuint8 *)(void*)(&__IPSBAR[0x000C6E]))
#define MCF_INTC0_ICR47 (*(vuint8 *)(void*)(&__IPSBAR[0x000C6F]))
#define MCF_INTC0_ICR48 (*(vuint8 *)(void*)(&__IPSBAR[0x000C70]))
#define MCF_INTC0_ICR49 (*(vuint8 *)(void*)(&__IPSBAR[0x000C71]))
#define MCF_INTC0_ICR50 (*(vuint8 *)(void*)(&__IPSBAR[0x000C72]))
#define MCF_INTC0_ICR51 (*(vuint8 *)(void*)(&__IPSBAR[0x000C73]))
#define MCF_INTC0_ICR52 (*(vuint8 *)(void*)(&__IPSBAR[0x000C74]))
#define MCF_INTC0_ICR53 (*(vuint8 *)(void*)(&__IPSBAR[0x000C75]))
#define MCF_INTC0_ICR54 (*(vuint8 *)(void*)(&__IPSBAR[0x000C76]))
#define MCF_INTC0_ICR55 (*(vuint8 *)(void*)(&__IPSBAR[0x000C77]))
#define MCF_INTC0_ICR56 (*(vuint8 *)(void*)(&__IPSBAR[0x000C78]))
#define MCF_INTC0_ICR57 (*(vuint8 *)(void*)(&__IPSBAR[0x000C79]))
#define MCF_INTC0_ICR58 (*(vuint8 *)(void*)(&__IPSBAR[0x000C7A]))
#define MCF_INTC0_ICR59 (*(vuint8 *)(void*)(&__IPSBAR[0x000C7B]))
#define MCF_INTC0_ICR60 (*(vuint8 *)(void*)(&__IPSBAR[0x000C7C]))
#define MCF_INTC0_ICR61 (*(vuint8 *)(void*)(&__IPSBAR[0x000C7D]))
#define MCF_INTC0_ICR62 (*(vuint8 *)(void*)(&__IPSBAR[0x000C7E]))
#define MCF_INTC0_ICR63 (*(vuint8 *)(void*)(&__IPSBAR[0x000C7F]))
#define MCF_INTC0_ICRn(x) (*(vuint8 *)(void*)(&__IPSBAR[0x000C40+((x)*0x001)]))
#define MCF_INTC0_SWIACK (*(vuint8 *)(void*)(&__IPSBAR[0x000CE0]))
#define MCF_INTC0_L1IACK (*(vuint8 *)(void*)(&__IPSBAR[0x000CE4]))
#define MCF_INTC0_L2IACK (*(vuint8 *)(void*)(&__IPSBAR[0x000CE8]))
#define MCF_INTC0_L3IACK (*(vuint8 *)(void*)(&__IPSBAR[0x000CEC]))
#define MCF_INTC0_L4IACK (*(vuint8 *)(void*)(&__IPSBAR[0x000CF0]))
#define MCF_INTC0_L5IACK (*(vuint8 *)(void*)(&__IPSBAR[0x000CF4]))
#define MCF_INTC0_L6IACK (*(vuint8 *)(void*)(&__IPSBAR[0x000CF8]))
#define MCF_INTC0_L7IACK (*(vuint8 *)(void*)(&__IPSBAR[0x000CFC]))
#define MCF_INTC0_LnIACK(x) (*(vuint8 *)(void*)(&__IPSBAR[0x000CE4+((x)*0x004)]))
/* Bit definitions and macros for MCF_INTC0_IPRH */
#define MCF_INTC0_IPRH_INT32 (0x00000001)
#define MCF_INTC0_IPRH_INT33 (0x00000002)
#define MCF_INTC0_IPRH_INT34 (0x00000004)
#define MCF_INTC0_IPRH_INT35 (0x00000008)
#define MCF_INTC0_IPRH_INT36 (0x00000010)
#define MCF_INTC0_IPRH_INT37 (0x00000020)
#define MCF_INTC0_IPRH_INT38 (0x00000040)
#define MCF_INTC0_IPRH_INT39 (0x00000080)
#define MCF_INTC0_IPRH_INT40 (0x00000100)
#define MCF_INTC0_IPRH_INT41 (0x00000200)
#define MCF_INTC0_IPRH_INT42 (0x00000400)
#define MCF_INTC0_IPRH_INT43 (0x00000800)
#define MCF_INTC0_IPRH_INT44 (0x00001000)
#define MCF_INTC0_IPRH_INT45 (0x00002000)
#define MCF_INTC0_IPRH_INT46 (0x00004000)
#define MCF_INTC0_IPRH_INT47 (0x00008000)
#define MCF_INTC0_IPRH_INT48 (0x00010000)
#define MCF_INTC0_IPRH_INT49 (0x00020000)
#define MCF_INTC0_IPRH_INT50 (0x00040000)
#define MCF_INTC0_IPRH_INT51 (0x00080000)
#define MCF_INTC0_IPRH_INT52 (0x00100000)
#define MCF_INTC0_IPRH_INT53 (0x00200000)
#define MCF_INTC0_IPRH_INT54 (0x00400000)
#define MCF_INTC0_IPRH_INT55 (0x00800000)
#define MCF_INTC0_IPRH_INT56 (0x01000000)
#define MCF_INTC0_IPRH_INT57 (0x02000000)
#define MCF_INTC0_IPRH_INT58 (0x04000000)
#define MCF_INTC0_IPRH_INT59 (0x08000000)
#define MCF_INTC0_IPRH_INT60 (0x10000000)
#define MCF_INTC0_IPRH_INT61 (0x20000000)
#define MCF_INTC0_IPRH_INT62 (0x40000000)
#define MCF_INTC0_IPRH_INT63 (0x80000000)
/* Bit definitions and macros for MCF_INTC0_IPRL */
#define MCF_INTC0_IPRL_INT1 (0x00000002)
#define MCF_INTC0_IPRL_INT2 (0x00000004)
#define MCF_INTC0_IPRL_INT3 (0x00000008)
#define MCF_INTC0_IPRL_INT4 (0x00000010)
#define MCF_INTC0_IPRL_INT5 (0x00000020)
#define MCF_INTC0_IPRL_INT6 (0x00000040)
#define MCF_INTC0_IPRL_INT7 (0x00000080)
#define MCF_INTC0_IPRL_INT8 (0x00000100)
#define MCF_INTC0_IPRL_INT9 (0x00000200)
#define MCF_INTC0_IPRL_INT10 (0x00000400)
#define MCF_INTC0_IPRL_INT11 (0x00000800)
#define MCF_INTC0_IPRL_INT12 (0x00001000)
#define MCF_INTC0_IPRL_INT13 (0x00002000)
#define MCF_INTC0_IPRL_INT14 (0x00004000)
#define MCF_INTC0_IPRL_INT15 (0x00008000)
#define MCF_INTC0_IPRL_INT16 (0x00010000)
#define MCF_INTC0_IPRL_INT17 (0x00020000)
#define MCF_INTC0_IPRL_INT18 (0x00040000)
#define MCF_INTC0_IPRL_INT19 (0x00080000)
#define MCF_INTC0_IPRL_INT20 (0x00100000)
#define MCF_INTC0_IPRL_INT21 (0x00200000)
#define MCF_INTC0_IPRL_INT22 (0x00400000)
#define MCF_INTC0_IPRL_INT23 (0x00800000)
#define MCF_INTC0_IPRL_INT24 (0x01000000)
#define MCF_INTC0_IPRL_INT25 (0x02000000)
#define MCF_INTC0_IPRL_INT26 (0x04000000)
#define MCF_INTC0_IPRL_INT27 (0x08000000)
#define MCF_INTC0_IPRL_INT28 (0x10000000)
#define MCF_INTC0_IPRL_INT29 (0x20000000)
#define MCF_INTC0_IPRL_INT30 (0x40000000)
#define MCF_INTC0_IPRL_INT31 (0x80000000)
/* Bit definitions and macros for MCF_INTC0_IMRH */
#define MCF_INTC0_IMRH_INT_MASK32 (0x00000001)
#define MCF_INTC0_IMRH_INT_MASK33 (0x00000002)
#define MCF_INTC0_IMRH_INT_MASK34 (0x00000004)
#define MCF_INTC0_IMRH_INT_MASK35 (0x00000008)
#define MCF_INTC0_IMRH_INT_MASK36 (0x00000010)
#define MCF_INTC0_IMRH_INT_MASK37 (0x00000020)
#define MCF_INTC0_IMRH_INT_MASK38 (0x00000040)
#define MCF_INTC0_IMRH_INT_MASK39 (0x00000080)
#define MCF_INTC0_IMRH_INT_MASK40 (0x00000100)
#define MCF_INTC0_IMRH_INT_MASK41 (0x00000200)
#define MCF_INTC0_IMRH_INT_MASK42 (0x00000400)
#define MCF_INTC0_IMRH_INT_MASK43 (0x00000800)
#define MCF_INTC0_IMRH_INT_MASK44 (0x00001000)
#define MCF_INTC0_IMRH_INT_MASK45 (0x00002000)
#define MCF_INTC0_IMRH_INT_MASK46 (0x00004000)
#define MCF_INTC0_IMRH_INT_MASK47 (0x00008000)
#define MCF_INTC0_IMRH_INT_MASK48 (0x00010000)
#define MCF_INTC0_IMRH_INT_MASK49 (0x00020000)
#define MCF_INTC0_IMRH_INT_MASK50 (0x00040000)
#define MCF_INTC0_IMRH_INT_MASK51 (0x00080000)
#define MCF_INTC0_IMRH_INT_MASK52 (0x00100000)
#define MCF_INTC0_IMRH_INT_MASK53 (0x00200000)
#define MCF_INTC0_IMRH_INT_MASK54 (0x00400000)
#define MCF_INTC0_IMRH_INT_MASK55 (0x00800000)
#define MCF_INTC0_IMRH_INT_MASK56 (0x01000000)
#define MCF_INTC0_IMRH_INT_MASK57 (0x02000000)
#define MCF_INTC0_IMRH_INT_MASK58 (0x04000000)
#define MCF_INTC0_IMRH_INT_MASK59 (0x08000000)
#define MCF_INTC0_IMRH_INT_MASK60 (0x10000000)
#define MCF_INTC0_IMRH_INT_MASK61 (0x20000000)
#define MCF_INTC0_IMRH_INT_MASK62 (0x40000000)
#define MCF_INTC0_IMRH_INT_MASK63 (0x80000000)
/* Bit definitions and macros for MCF_INTC0_IMRL */
#define MCF_INTC0_IMRL_MASKALL (0x00000001)
#define MCF_INTC0_IMRL_INT_MASK1 (0x00000002)
#define MCF_INTC0_IMRL_INT_MASK2 (0x00000004)
#define MCF_INTC0_IMRL_INT_MASK3 (0x00000008)
#define MCF_INTC0_IMRL_INT_MASK4 (0x00000010)
#define MCF_INTC0_IMRL_INT_MASK5 (0x00000020)
#define MCF_INTC0_IMRL_INT_MASK6 (0x00000040)
#define MCF_INTC0_IMRL_INT_MASK7 (0x00000080)
#define MCF_INTC0_IMRL_INT_MASK8 (0x00000100)
#define MCF_INTC0_IMRL_INT_MASK9 (0x00000200)
#define MCF_INTC0_IMRL_INT_MASK10 (0x00000400)
#define MCF_INTC0_IMRL_INT_MASK11 (0x00000800)
#define MCF_INTC0_IMRL_INT_MASK12 (0x00001000)
#define MCF_INTC0_IMRL_INT_MASK13 (0x00002000)
#define MCF_INTC0_IMRL_INT_MASK14 (0x00004000)
#define MCF_INTC0_IMRL_INT_MASK15 (0x00008000)
#define MCF_INTC0_IMRL_INT_MASK16 (0x00010000)
#define MCF_INTC0_IMRL_INT_MASK17 (0x00020000)
#define MCF_INTC0_IMRL_INT_MASK18 (0x00040000)
#define MCF_INTC0_IMRL_INT_MASK19 (0x00080000)
#define MCF_INTC0_IMRL_INT_MASK20 (0x00100000)
#define MCF_INTC0_IMRL_INT_MASK21 (0x00200000)
#define MCF_INTC0_IMRL_INT_MASK22 (0x00400000)
#define MCF_INTC0_IMRL_INT_MASK23 (0x00800000)
#define MCF_INTC0_IMRL_INT_MASK24 (0x01000000)
#define MCF_INTC0_IMRL_INT_MASK25 (0x02000000)
#define MCF_INTC0_IMRL_INT_MASK26 (0x04000000)
#define MCF_INTC0_IMRL_INT_MASK27 (0x08000000)
#define MCF_INTC0_IMRL_INT_MASK28 (0x10000000)
#define MCF_INTC0_IMRL_INT_MASK29 (0x20000000)
#define MCF_INTC0_IMRL_INT_MASK30 (0x40000000)
#define MCF_INTC0_IMRL_INT_MASK31 (0x80000000)
/* Bit definitions and macros for MCF_INTC0_INTFRCH */
#define MCF_INTC0_INTFRCH_INTFRC32 (0x00000001)
#define MCF_INTC0_INTFRCH_INTFRC33 (0x00000002)
#define MCF_INTC0_INTFRCH_INTFRC34 (0x00000004)
#define MCF_INTC0_INTFRCH_INTFRC35 (0x00000008)
#define MCF_INTC0_INTFRCH_INTFRC36 (0x00000010)
#define MCF_INTC0_INTFRCH_INTFRC37 (0x00000020)
#define MCF_INTC0_INTFRCH_INTFRC38 (0x00000040)
#define MCF_INTC0_INTFRCH_INTFRC39 (0x00000080)
#define MCF_INTC0_INTFRCH_INTFRC40 (0x00000100)
#define MCF_INTC0_INTFRCH_INTFRC41 (0x00000200)
#define MCF_INTC0_INTFRCH_INTFRC42 (0x00000400)
#define MCF_INTC0_INTFRCH_INTFRC43 (0x00000800)
#define MCF_INTC0_INTFRCH_INTFRC44 (0x00001000)
#define MCF_INTC0_INTFRCH_INTFRC45 (0x00002000)
#define MCF_INTC0_INTFRCH_INTFRC46 (0x00004000)
#define MCF_INTC0_INTFRCH_INTFRC47 (0x00008000)
#define MCF_INTC0_INTFRCH_INTFRC48 (0x00010000)
#define MCF_INTC0_INTFRCH_INTFRC49 (0x00020000)
#define MCF_INTC0_INTFRCH_INTFRC50 (0x00040000)
#define MCF_INTC0_INTFRCH_INTFRC51 (0x00080000)
#define MCF_INTC0_INTFRCH_INTFRC52 (0x00100000)
#define MCF_INTC0_INTFRCH_INTFRC53 (0x00200000)
#define MCF_INTC0_INTFRCH_INTFRC54 (0x00400000)
#define MCF_INTC0_INTFRCH_INTFRC55 (0x00800000)
#define MCF_INTC0_INTFRCH_INTFRC56 (0x01000000)
#define MCF_INTC0_INTFRCH_INTFRC57 (0x02000000)
#define MCF_INTC0_INTFRCH_INTFRC58 (0x04000000)
#define MCF_INTC0_INTFRCH_INTFRC59 (0x08000000)
#define MCF_INTC0_INTFRCH_INTFRC60 (0x10000000)
#define MCF_INTC0_INTFRCH_INTFRC61 (0x20000000)
#define MCF_INTC0_INTFRCH_INTFRC62 (0x40000000)
#define MCF_INTC0_INTFRCH_INTFRC63 (0x80000000)
/* Bit definitions and macros for MCF_INTC0_INTFRCL */
#define MCF_INTC0_INTFRCL_INTFRC1 (0x00000002)
#define MCF_INTC0_INTFRCL_INTFRC2 (0x00000004)
#define MCF_INTC0_INTFRCL_INTFRC3 (0x00000008)
#define MCF_INTC0_INTFRCL_INTFRC4 (0x00000010)
#define MCF_INTC0_INTFRCL_INTFRC5 (0x00000020)
#define MCF_INTC0_INTFRCL_INT6 (0x00000040)
#define MCF_INTC0_INTFRCL_INT7 (0x00000080)
#define MCF_INTC0_INTFRCL_INT8 (0x00000100)
#define MCF_INTC0_INTFRCL_INT9 (0x00000200)
#define MCF_INTC0_INTFRCL_INT10 (0x00000400)
#define MCF_INTC0_INTFRCL_INTFRC11 (0x00000800)
#define MCF_INTC0_INTFRCL_INTFRC12 (0x00001000)
#define MCF_INTC0_INTFRCL_INTFRC13 (0x00002000)
#define MCF_INTC0_INTFRCL_INTFRC14 (0x00004000)
#define MCF_INTC0_INTFRCL_INT15 (0x00008000)
#define MCF_INTC0_INTFRCL_INTFRC16 (0x00010000)
#define MCF_INTC0_INTFRCL_INTFRC17 (0x00020000)
#define MCF_INTC0_INTFRCL_INTFRC18 (0x00040000)
#define MCF_INTC0_INTFRCL_INTFRC19 (0x00080000)
#define MCF_INTC0_INTFRCL_INTFRC20 (0x00100000)
#define MCF_INTC0_INTFRCL_INTFRC21 (0x00200000)
#define MCF_INTC0_INTFRCL_INTFRC22 (0x00400000)
#define MCF_INTC0_INTFRCL_INTFRC23 (0x00800000)
#define MCF_INTC0_INTFRCL_INTFRC24 (0x01000000)
#define MCF_INTC0_INTFRCL_INTFRC25 (0x02000000)
#define MCF_INTC0_INTFRCL_INTFRC26 (0x04000000)
#define MCF_INTC0_INTFRCL_INTFRC27 (0x08000000)
#define MCF_INTC0_INTFRCL_INTFRC28 (0x10000000)
#define MCF_INTC0_INTFRCL_INTFRC29 (0x20000000)
#define MCF_INTC0_INTFRCL_INTFRC30 (0x40000000)
#define MCF_INTC0_INTFRCL_INTFRC31 (0x80000000)
/* Bit definitions and macros for MCF_INTC0_IRLR */
#define MCF_INTC0_IRLR_IRQ(x) (((x)&0x7F)<<1)
/* Bit definitions and macros for MCF_INTC0_IACKLPR */
#define MCF_INTC0_IACKLPR_PRI(x) (((x)&0x0F)<<0)
#define MCF_INTC0_IACKLPR_LEVEL(x) (((x)&0x07)<<4)
/* Bit definitions and macros for MCF_INTC0_ICRn */
#define MCF_INTC0_ICRn_IP(x) (((x)&0x07)<<0)
#define MCF_INTC0_ICRn_IL(x) (((x)&0x07)<<3)
/********************************************************************/
#endif /* __MCF523X_INTC0_H__ */

View File

@@ -0,0 +1,317 @@
/*
* File: mcf523x_intc1.h
* Purpose: Register and bit definitions for the MCF523X
*
* Notes:
*
*/
#ifndef __MCF523X_INTC1_H__
#define __MCF523X_INTC1_H__
/*********************************************************************
*
* Interrupt Controller 1 (INTC1)
*
*********************************************************************/
/* Register read/write macros */
#define MCF_INTC1_IPRH (*(vuint32*)(void*)(&__IPSBAR[0x000D00]))
#define MCF_INTC1_IPRL (*(vuint32*)(void*)(&__IPSBAR[0x000D04]))
#define MCF_INTC1_IMRH (*(vuint32*)(void*)(&__IPSBAR[0x000D08]))
#define MCF_INTC1_IMRL (*(vuint32*)(void*)(&__IPSBAR[0x000D0C]))
#define MCF_INTC1_INTFRCH (*(vuint32*)(void*)(&__IPSBAR[0x000D10]))
#define MCF_INTC1_INTFRCL (*(vuint32*)(void*)(&__IPSBAR[0x000D14]))
#define MCF_INTC1_IRLR (*(vuint8 *)(void*)(&__IPSBAR[0x000D18]))
#define MCF_INTC1_IACKLPR (*(vuint8 *)(void*)(&__IPSBAR[0x000D19]))
#define MCF_INTC1_ICR0 (*(vuint8 *)(void*)(&__IPSBAR[0x000D40]))
#define MCF_INTC1_ICR1 (*(vuint8 *)(void*)(&__IPSBAR[0x000D41]))
#define MCF_INTC1_ICR2 (*(vuint8 *)(void*)(&__IPSBAR[0x000D42]))
#define MCF_INTC1_ICR3 (*(vuint8 *)(void*)(&__IPSBAR[0x000D43]))
#define MCF_INTC1_ICR4 (*(vuint8 *)(void*)(&__IPSBAR[0x000D44]))
#define MCF_INTC1_ICR5 (*(vuint8 *)(void*)(&__IPSBAR[0x000D45]))
#define MCF_INTC1_ICR6 (*(vuint8 *)(void*)(&__IPSBAR[0x000D46]))
#define MCF_INTC1_ICR7 (*(vuint8 *)(void*)(&__IPSBAR[0x000D47]))
#define MCF_INTC1_ICR8 (*(vuint8 *)(void*)(&__IPSBAR[0x000D48]))
#define MCF_INTC1_ICR9 (*(vuint8 *)(void*)(&__IPSBAR[0x000D49]))
#define MCF_INTC1_ICR10 (*(vuint8 *)(void*)(&__IPSBAR[0x000D4A]))
#define MCF_INTC1_ICR11 (*(vuint8 *)(void*)(&__IPSBAR[0x000D4B]))
#define MCF_INTC1_ICR12 (*(vuint8 *)(void*)(&__IPSBAR[0x000D4C]))
#define MCF_INTC1_ICR13 (*(vuint8 *)(void*)(&__IPSBAR[0x000D4D]))
#define MCF_INTC1_ICR14 (*(vuint8 *)(void*)(&__IPSBAR[0x000D4E]))
#define MCF_INTC1_ICR15 (*(vuint8 *)(void*)(&__IPSBAR[0x000D4F]))
#define MCF_INTC1_ICR16 (*(vuint8 *)(void*)(&__IPSBAR[0x000D50]))
#define MCF_INTC1_ICR17 (*(vuint8 *)(void*)(&__IPSBAR[0x000D51]))
#define MCF_INTC1_ICR18 (*(vuint8 *)(void*)(&__IPSBAR[0x000D52]))
#define MCF_INTC1_ICR19 (*(vuint8 *)(void*)(&__IPSBAR[0x000D53]))
#define MCF_INTC1_ICR20 (*(vuint8 *)(void*)(&__IPSBAR[0x000D54]))
#define MCF_INTC1_ICR21 (*(vuint8 *)(void*)(&__IPSBAR[0x000D55]))
#define MCF_INTC1_ICR22 (*(vuint8 *)(void*)(&__IPSBAR[0x000D56]))
#define MCF_INTC1_ICR23 (*(vuint8 *)(void*)(&__IPSBAR[0x000D57]))
#define MCF_INTC1_ICR24 (*(vuint8 *)(void*)(&__IPSBAR[0x000D58]))
#define MCF_INTC1_ICR25 (*(vuint8 *)(void*)(&__IPSBAR[0x000D59]))
#define MCF_INTC1_ICR26 (*(vuint8 *)(void*)(&__IPSBAR[0x000D5A]))
#define MCF_INTC1_ICR27 (*(vuint8 *)(void*)(&__IPSBAR[0x000D5B]))
#define MCF_INTC1_ICR28 (*(vuint8 *)(void*)(&__IPSBAR[0x000D5C]))
#define MCF_INTC1_ICR29 (*(vuint8 *)(void*)(&__IPSBAR[0x000D5D]))
#define MCF_INTC1_ICR30 (*(vuint8 *)(void*)(&__IPSBAR[0x000D5E]))
#define MCF_INTC1_ICR31 (*(vuint8 *)(void*)(&__IPSBAR[0x000D5F]))
#define MCF_INTC1_ICR32 (*(vuint8 *)(void*)(&__IPSBAR[0x000D60]))
#define MCF_INTC1_ICR33 (*(vuint8 *)(void*)(&__IPSBAR[0x000D61]))
#define MCF_INTC1_ICR34 (*(vuint8 *)(void*)(&__IPSBAR[0x000D62]))
#define MCF_INTC1_ICR35 (*(vuint8 *)(void*)(&__IPSBAR[0x000D63]))
#define MCF_INTC1_ICR36 (*(vuint8 *)(void*)(&__IPSBAR[0x000D64]))
#define MCF_INTC1_ICR37 (*(vuint8 *)(void*)(&__IPSBAR[0x000D65]))
#define MCF_INTC1_ICR38 (*(vuint8 *)(void*)(&__IPSBAR[0x000D66]))
#define MCF_INTC1_ICR39 (*(vuint8 *)(void*)(&__IPSBAR[0x000D67]))
#define MCF_INTC1_ICR40 (*(vuint8 *)(void*)(&__IPSBAR[0x000D68]))
#define MCF_INTC1_ICR41 (*(vuint8 *)(void*)(&__IPSBAR[0x000D69]))
#define MCF_INTC1_ICR42 (*(vuint8 *)(void*)(&__IPSBAR[0x000D6A]))
#define MCF_INTC1_ICR43 (*(vuint8 *)(void*)(&__IPSBAR[0x000D6B]))
#define MCF_INTC1_ICR44 (*(vuint8 *)(void*)(&__IPSBAR[0x000D6C]))
#define MCF_INTC1_ICR45 (*(vuint8 *)(void*)(&__IPSBAR[0x000D6D]))
#define MCF_INTC1_ICR46 (*(vuint8 *)(void*)(&__IPSBAR[0x000D6E]))
#define MCF_INTC1_ICR47 (*(vuint8 *)(void*)(&__IPSBAR[0x000D6F]))
#define MCF_INTC1_ICR48 (*(vuint8 *)(void*)(&__IPSBAR[0x000D70]))
#define MCF_INTC1_ICR49 (*(vuint8 *)(void*)(&__IPSBAR[0x000D71]))
#define MCF_INTC1_ICR50 (*(vuint8 *)(void*)(&__IPSBAR[0x000D72]))
#define MCF_INTC1_ICR51 (*(vuint8 *)(void*)(&__IPSBAR[0x000D73]))
#define MCF_INTC1_ICR52 (*(vuint8 *)(void*)(&__IPSBAR[0x000D74]))
#define MCF_INTC1_ICR53 (*(vuint8 *)(void*)(&__IPSBAR[0x000D75]))
#define MCF_INTC1_ICR54 (*(vuint8 *)(void*)(&__IPSBAR[0x000D76]))
#define MCF_INTC1_ICR55 (*(vuint8 *)(void*)(&__IPSBAR[0x000D77]))
#define MCF_INTC1_ICR56 (*(vuint8 *)(void*)(&__IPSBAR[0x000D78]))
#define MCF_INTC1_ICR57 (*(vuint8 *)(void*)(&__IPSBAR[0x000D79]))
#define MCF_INTC1_ICR58 (*(vuint8 *)(void*)(&__IPSBAR[0x000D7A]))
#define MCF_INTC1_ICR59 (*(vuint8 *)(void*)(&__IPSBAR[0x000D7B]))
#define MCF_INTC1_ICR60 (*(vuint8 *)(void*)(&__IPSBAR[0x000D7C]))
#define MCF_INTC1_ICR61 (*(vuint8 *)(void*)(&__IPSBAR[0x000D7D]))
#define MCF_INTC1_ICR62 (*(vuint8 *)(void*)(&__IPSBAR[0x000D7E]))
#define MCF_INTC1_ICR63 (*(vuint8 *)(void*)(&__IPSBAR[0x000D7F]))
#define MCF_INTC1_ICRn(x) (*(vuint8 *)(void*)(&__IPSBAR[0x000D40+((x)*0x001)]))
#define MCF_INTC1_SWIACK (*(vuint8 *)(void*)(&__IPSBAR[0x000DE0]))
#define MCF_INTC1_L1IACK (*(vuint8 *)(void*)(&__IPSBAR[0x000DE4]))
#define MCF_INTC1_L2IACK (*(vuint8 *)(void*)(&__IPSBAR[0x000DE8]))
#define MCF_INTC1_L3IACK (*(vuint8 *)(void*)(&__IPSBAR[0x000DEC]))
#define MCF_INTC1_L4IACK (*(vuint8 *)(void*)(&__IPSBAR[0x000DF0]))
#define MCF_INTC1_L5IACK (*(vuint8 *)(void*)(&__IPSBAR[0x000DF4]))
#define MCF_INTC1_L6IACK (*(vuint8 *)(void*)(&__IPSBAR[0x000DF8]))
#define MCF_INTC1_L7IACK (*(vuint8 *)(void*)(&__IPSBAR[0x000DFC]))
#define MCF_INTC1_LnIACK(x) (*(vuint8 *)(void*)(&__IPSBAR[0x000DE4+((x)*0x004)]))
/* Bit definitions and macros for MCF_INTC1_IPRH */
#define MCF_INTC1_IPRH_INT32 (0x00000001)
#define MCF_INTC1_IPRH_INT33 (0x00000002)
#define MCF_INTC1_IPRH_INT34 (0x00000004)
#define MCF_INTC1_IPRH_INT35 (0x00000008)
#define MCF_INTC1_IPRH_INT36 (0x00000010)
#define MCF_INTC1_IPRH_INT37 (0x00000020)
#define MCF_INTC1_IPRH_INT38 (0x00000040)
#define MCF_INTC1_IPRH_INT39 (0x00000080)
#define MCF_INTC1_IPRH_INT40 (0x00000100)
#define MCF_INTC1_IPRH_INT41 (0x00000200)
#define MCF_INTC1_IPRH_INT42 (0x00000400)
#define MCF_INTC1_IPRH_INT43 (0x00000800)
#define MCF_INTC1_IPRH_INT44 (0x00001000)
#define MCF_INTC1_IPRH_INT45 (0x00002000)
#define MCF_INTC1_IPRH_INT46 (0x00004000)
#define MCF_INTC1_IPRH_INT47 (0x00008000)
#define MCF_INTC1_IPRH_INT48 (0x00010000)
#define MCF_INTC1_IPRH_INT49 (0x00020000)
#define MCF_INTC1_IPRH_INT50 (0x00040000)
#define MCF_INTC1_IPRH_INT51 (0x00080000)
#define MCF_INTC1_IPRH_INT52 (0x00100000)
#define MCF_INTC1_IPRH_INT53 (0x00200000)
#define MCF_INTC1_IPRH_INT54 (0x00400000)
#define MCF_INTC1_IPRH_INT55 (0x00800000)
#define MCF_INTC1_IPRH_INT56 (0x01000000)
#define MCF_INTC1_IPRH_INT57 (0x02000000)
#define MCF_INTC1_IPRH_INT58 (0x04000000)
#define MCF_INTC1_IPRH_INT59 (0x08000000)
#define MCF_INTC1_IPRH_INT60 (0x10000000)
#define MCF_INTC1_IPRH_INT61 (0x20000000)
#define MCF_INTC1_IPRH_INT62 (0x40000000)
#define MCF_INTC1_IPRH_INT63 (0x80000000)
/* Bit definitions and macros for MCF_INTC1_IPRL */
#define MCF_INTC1_IPRL_INT1 (0x00000002)
#define MCF_INTC1_IPRL_INT2 (0x00000004)
#define MCF_INTC1_IPRL_INT3 (0x00000008)
#define MCF_INTC1_IPRL_INT4 (0x00000010)
#define MCF_INTC1_IPRL_INT5 (0x00000020)
#define MCF_INTC1_IPRL_INT6 (0x00000040)
#define MCF_INTC1_IPRL_INT7 (0x00000080)
#define MCF_INTC1_IPRL_INT8 (0x00000100)
#define MCF_INTC1_IPRL_INT9 (0x00000200)
#define MCF_INTC1_IPRL_INT10 (0x00000400)
#define MCF_INTC1_IPRL_INT11 (0x00000800)
#define MCF_INTC1_IPRL_INT12 (0x00001000)
#define MCF_INTC1_IPRL_INT13 (0x00002000)
#define MCF_INTC1_IPRL_INT14 (0x00004000)
#define MCF_INTC1_IPRL_INT15 (0x00008000)
#define MCF_INTC1_IPRL_INT16 (0x00010000)
#define MCF_INTC1_IPRL_INT17 (0x00020000)
#define MCF_INTC1_IPRL_INT18 (0x00040000)
#define MCF_INTC1_IPRL_INT19 (0x00080000)
#define MCF_INTC1_IPRL_INT20 (0x00100000)
#define MCF_INTC1_IPRL_INT21 (0x00200000)
#define MCF_INTC1_IPRL_INT22 (0x00400000)
#define MCF_INTC1_IPRL_INT23 (0x00800000)
#define MCF_INTC1_IPRL_INT24 (0x01000000)
#define MCF_INTC1_IPRL_INT25 (0x02000000)
#define MCF_INTC1_IPRL_INT26 (0x04000000)
#define MCF_INTC1_IPRL_INT27 (0x08000000)
#define MCF_INTC1_IPRL_INT28 (0x10000000)
#define MCF_INTC1_IPRL_INT29 (0x20000000)
#define MCF_INTC1_IPRL_INT30 (0x40000000)
#define MCF_INTC1_IPRL_INT31 (0x80000000)
/* Bit definitions and macros for MCF_INTC1_IMRH */
#define MCF_INTC1_IMRH_INT_MASK32 (0x00000001)
#define MCF_INTC1_IMRH_INT_MASK33 (0x00000002)
#define MCF_INTC1_IMRH_INT_MASK34 (0x00000004)
#define MCF_INTC1_IMRH_INT_MASK35 (0x00000008)
#define MCF_INTC1_IMRH_INT_MASK36 (0x00000010)
#define MCF_INTC1_IMRH_INT_MASK37 (0x00000020)
#define MCF_INTC1_IMRH_INT_MASK38 (0x00000040)
#define MCF_INTC1_IMRH_INT_MASK39 (0x00000080)
#define MCF_INTC1_IMRH_INT_MASK40 (0x00000100)
#define MCF_INTC1_IMRH_INT_MASK41 (0x00000200)
#define MCF_INTC1_IMRH_INT_MASK42 (0x00000400)
#define MCF_INTC1_IMRH_INT_MASK43 (0x00000800)
#define MCF_INTC1_IMRH_INT_MASK44 (0x00001000)
#define MCF_INTC1_IMRH_INT_MASK45 (0x00002000)
#define MCF_INTC1_IMRH_INT_MASK46 (0x00004000)
#define MCF_INTC1_IMRH_INT_MASK47 (0x00008000)
#define MCF_INTC1_IMRH_INT_MASK48 (0x00010000)
#define MCF_INTC1_IMRH_INT_MASK49 (0x00020000)
#define MCF_INTC1_IMRH_INT_MASK50 (0x00040000)
#define MCF_INTC1_IMRH_INT_MASK51 (0x00080000)
#define MCF_INTC1_IMRH_INT_MASK52 (0x00100000)
#define MCF_INTC1_IMRH_INT_MASK53 (0x00200000)
#define MCF_INTC1_IMRH_INT_MASK54 (0x00400000)
#define MCF_INTC1_IMRH_INT_MASK55 (0x00800000)
#define MCF_INTC1_IMRH_INT_MASK56 (0x01000000)
#define MCF_INTC1_IMRH_INT_MASK57 (0x02000000)
#define MCF_INTC1_IMRH_INT_MASK58 (0x04000000)
#define MCF_INTC1_IMRH_INT_MASK59 (0x08000000)
#define MCF_INTC1_IMRH_INT_MASK60 (0x10000000)
#define MCF_INTC1_IMRH_INT_MASK61 (0x20000000)
#define MCF_INTC1_IMRH_INT_MASK62 (0x40000000)
#define MCF_INTC1_IMRH_INT_MASK63 (0x80000000)
/* Bit definitions and macros for MCF_INTC1_IMRL */
#define MCF_INTC1_IMRL_MASKALL (0x00000001)
#define MCF_INTC1_IMRL_INT_MASK1 (0x00000002)
#define MCF_INTC1_IMRL_INT_MASK2 (0x00000004)
#define MCF_INTC1_IMRL_INT_MASK3 (0x00000008)
#define MCF_INTC1_IMRL_INT_MASK4 (0x00000010)
#define MCF_INTC1_IMRL_INT_MASK5 (0x00000020)
#define MCF_INTC1_IMRL_INT_MASK6 (0x00000040)
#define MCF_INTC1_IMRL_INT_MASK7 (0x00000080)
#define MCF_INTC1_IMRL_INT_MASK8 (0x00000100)
#define MCF_INTC1_IMRL_INT_MASK9 (0x00000200)
#define MCF_INTC1_IMRL_INT_MASK10 (0x00000400)
#define MCF_INTC1_IMRL_INT_MASK11 (0x00000800)
#define MCF_INTC1_IMRL_INT_MASK12 (0x00001000)
#define MCF_INTC1_IMRL_INT_MASK13 (0x00002000)
#define MCF_INTC1_IMRL_INT_MASK14 (0x00004000)
#define MCF_INTC1_IMRL_INT_MASK15 (0x00008000)
#define MCF_INTC1_IMRL_INT_MASK16 (0x00010000)
#define MCF_INTC1_IMRL_INT_MASK17 (0x00020000)
#define MCF_INTC1_IMRL_INT_MASK18 (0x00040000)
#define MCF_INTC1_IMRL_INT_MASK19 (0x00080000)
#define MCF_INTC1_IMRL_INT_MASK20 (0x00100000)
#define MCF_INTC1_IMRL_INT_MASK21 (0x00200000)
#define MCF_INTC1_IMRL_INT_MASK22 (0x00400000)
#define MCF_INTC1_IMRL_INT_MASK23 (0x00800000)
#define MCF_INTC1_IMRL_INT_MASK24 (0x01000000)
#define MCF_INTC1_IMRL_INT_MASK25 (0x02000000)
#define MCF_INTC1_IMRL_INT_MASK26 (0x04000000)
#define MCF_INTC1_IMRL_INT_MASK27 (0x08000000)
#define MCF_INTC1_IMRL_INT_MASK28 (0x10000000)
#define MCF_INTC1_IMRL_INT_MASK29 (0x20000000)
#define MCF_INTC1_IMRL_INT_MASK30 (0x40000000)
#define MCF_INTC1_IMRL_INT_MASK31 (0x80000000)
/* Bit definitions and macros for MCF_INTC1_INTFRCH */
#define MCF_INTC1_INTFRCH_INTFRC32 (0x00000001)
#define MCF_INTC1_INTFRCH_INTFRC33 (0x00000002)
#define MCF_INTC1_INTFRCH_INTFRC34 (0x00000004)
#define MCF_INTC1_INTFRCH_INTFRC35 (0x00000008)
#define MCF_INTC1_INTFRCH_INTFRC36 (0x00000010)
#define MCF_INTC1_INTFRCH_INTFRC37 (0x00000020)
#define MCF_INTC1_INTFRCH_INTFRC38 (0x00000040)
#define MCF_INTC1_INTFRCH_INTFRC39 (0x00000080)
#define MCF_INTC1_INTFRCH_INTFRC40 (0x00000100)
#define MCF_INTC1_INTFRCH_INTFRC41 (0x00000200)
#define MCF_INTC1_INTFRCH_INTFRC42 (0x00000400)
#define MCF_INTC1_INTFRCH_INTFRC43 (0x00000800)
#define MCF_INTC1_INTFRCH_INTFRC44 (0x00001000)
#define MCF_INTC1_INTFRCH_INTFRC45 (0x00002000)
#define MCF_INTC1_INTFRCH_INTFRC46 (0x00004000)
#define MCF_INTC1_INTFRCH_INTFRC47 (0x00008000)
#define MCF_INTC1_INTFRCH_INTFRC48 (0x00010000)
#define MCF_INTC1_INTFRCH_INTFRC49 (0x00020000)
#define MCF_INTC1_INTFRCH_INTFRC50 (0x00040000)
#define MCF_INTC1_INTFRCH_INTFRC51 (0x00080000)
#define MCF_INTC1_INTFRCH_INTFRC52 (0x00100000)
#define MCF_INTC1_INTFRCH_INTFRC53 (0x00200000)
#define MCF_INTC1_INTFRCH_INTFRC54 (0x00400000)
#define MCF_INTC1_INTFRCH_INTFRC55 (0x00800000)
#define MCF_INTC1_INTFRCH_INTFRC56 (0x01000000)
#define MCF_INTC1_INTFRCH_INTFRC57 (0x02000000)
#define MCF_INTC1_INTFRCH_INTFRC58 (0x04000000)
#define MCF_INTC1_INTFRCH_INTFRC59 (0x08000000)
#define MCF_INTC1_INTFRCH_INTFRC60 (0x10000000)
#define MCF_INTC1_INTFRCH_INTFRC61 (0x20000000)
#define MCF_INTC1_INTFRCH_INTFRC62 (0x40000000)
#define MCF_INTC1_INTFRCH_INTFRC63 (0x80000000)
/* Bit definitions and macros for MCF_INTC1_INTFRCL */
#define MCF_INTC1_INTFRCL_INTFRC1 (0x00000002)
#define MCF_INTC1_INTFRCL_INTFRC2 (0x00000004)
#define MCF_INTC1_INTFRCL_INTFRC3 (0x00000008)
#define MCF_INTC1_INTFRCL_INTFRC4 (0x00000010)
#define MCF_INTC1_INTFRCL_INTFRC5 (0x00000020)
#define MCF_INTC1_INTFRCL_INT6 (0x00000040)
#define MCF_INTC1_INTFRCL_INT7 (0x00000080)
#define MCF_INTC1_INTFRCL_INT8 (0x00000100)
#define MCF_INTC1_INTFRCL_INT9 (0x00000200)
#define MCF_INTC1_INTFRCL_INT10 (0x00000400)
#define MCF_INTC1_INTFRCL_INTFRC11 (0x00000800)
#define MCF_INTC1_INTFRCL_INTFRC12 (0x00001000)
#define MCF_INTC1_INTFRCL_INTFRC13 (0x00002000)
#define MCF_INTC1_INTFRCL_INTFRC14 (0x00004000)
#define MCF_INTC1_INTFRCL_INT15 (0x00008000)
#define MCF_INTC1_INTFRCL_INTFRC16 (0x00010000)
#define MCF_INTC1_INTFRCL_INTFRC17 (0x00020000)
#define MCF_INTC1_INTFRCL_INTFRC18 (0x00040000)
#define MCF_INTC1_INTFRCL_INTFRC19 (0x00080000)
#define MCF_INTC1_INTFRCL_INTFRC20 (0x00100000)
#define MCF_INTC1_INTFRCL_INTFRC21 (0x00200000)
#define MCF_INTC1_INTFRCL_INTFRC22 (0x00400000)
#define MCF_INTC1_INTFRCL_INTFRC23 (0x00800000)
#define MCF_INTC1_INTFRCL_INTFRC24 (0x01000000)
#define MCF_INTC1_INTFRCL_INTFRC25 (0x02000000)
#define MCF_INTC1_INTFRCL_INTFRC26 (0x04000000)
#define MCF_INTC1_INTFRCL_INTFRC27 (0x08000000)
#define MCF_INTC1_INTFRCL_INTFRC28 (0x10000000)
#define MCF_INTC1_INTFRCL_INTFRC29 (0x20000000)
#define MCF_INTC1_INTFRCL_INTFRC30 (0x40000000)
#define MCF_INTC1_INTFRCL_INTFRC31 (0x80000000)
/* Bit definitions and macros for MCF_INTC1_IRLR */
#define MCF_INTC1_IRLR_IRQ(x) (((x)&0x7F)<<1)
/* Bit definitions and macros for MCF_INTC1_IACKLPR */
#define MCF_INTC1_IACKLPR_PRI(x) (((x)&0x0F)<<0)
#define MCF_INTC1_IACKLPR_LEVEL(x) (((x)&0x07)<<4)
/* Bit definitions and macros for MCF_INTC1_ICRn */
#define MCF_INTC1_ICRn_IP(x) (((x)&0x07)<<0)
#define MCF_INTC1_ICRn_IL(x) (((x)&0x07)<<3)
/********************************************************************/
#endif /* __MCF523X_INTC1_H__ */

View File

@@ -0,0 +1,95 @@
/*
* File: mcf523x_mdha.h
* Purpose: Register and bit definitions for the MCF523X
*
* Notes:
*
*/
#ifndef __MCF523X_MDHA_H__
#define __MCF523X_MDHA_H__
/*********************************************************************
*
* Message Digest Hardware Accelerator (MDHA)
*
*********************************************************************/
/* Register read/write macros */
#define MCF_MDHA_MDMR (*(vuint32*)(void*)(&__IPSBAR[0x190000]))
#define MCF_MDHA_MDCR (*(vuint32*)(void*)(&__IPSBAR[0x190004]))
#define MCF_MDHA_MDCMR (*(vuint32*)(void*)(&__IPSBAR[0x190008]))
#define MCF_MDHA_MDSR (*(vuint32*)(void*)(&__IPSBAR[0x19000C]))
#define MCF_MDHA_MDISR (*(vuint32*)(void*)(&__IPSBAR[0x190010]))
#define MCF_MDHA_MDIMR (*(vuint32*)(void*)(&__IPSBAR[0x190014]))
#define MCF_MDHA_MDDSR (*(vuint32*)(void*)(&__IPSBAR[0x19001C]))
#define MCF_MDHA_MDIN (*(vuint32*)(void*)(&__IPSBAR[0x190020]))
#define MCF_MDHA_MDA0 (*(vuint32*)(void*)(&__IPSBAR[0x190030]))
#define MCF_MDHA_MDB0 (*(vuint32*)(void*)(&__IPSBAR[0x190034]))
#define MCF_MDHA_MDC0 (*(vuint32*)(void*)(&__IPSBAR[0x190038]))
#define MCF_MDHA_MDD0 (*(vuint32*)(void*)(&__IPSBAR[0x19003C]))
#define MCF_MDHA_MDE0 (*(vuint32*)(void*)(&__IPSBAR[0x190040]))
#define MCF_MDHA_MDMDS (*(vuint32*)(void*)(&__IPSBAR[0x190044]))
#define MCF_MDHA_MDA1 (*(vuint32*)(void*)(&__IPSBAR[0x190070]))
#define MCF_MDHA_MDB1 (*(vuint32*)(void*)(&__IPSBAR[0x190074]))
#define MCF_MDHA_MDC1 (*(vuint32*)(void*)(&__IPSBAR[0x190078]))
#define MCF_MDHA_MDD1 (*(vuint32*)(void*)(&__IPSBAR[0x19007C]))
#define MCF_MDHA_MDE1 (*(vuint32*)(void*)(&__IPSBAR[0x190080]))
/* Bit definitions and macros for MCF_MDHA_MDMR */
#define MCF_MDHA_MDMR_ALG (0x00000001)
#define MCF_MDHA_MDMR_PDATA (0x00000004)
#define MCF_MDHA_MDMR_MAC(x) (((x)&0x00000003)<<3)
#define MCF_MDHA_MDMR_INIT (0x00000020)
#define MCF_MDHA_MDMR_IPAD (0x00000040)
#define MCF_MDHA_MDMR_OPAD (0x00000080)
#define MCF_MDHA_MDMR_SWAP (0x00000100)
#define MCF_MDHA_MDMR_MACFULL (0x00000200)
#define MCF_MDHA_MDMR_SSL (0x00000400)
/* Bit definitions and macros for MCF_MDHA_MDCR */
#define MCF_MDHA_MDCR_IE (0x00000001)
/* Bit definitions and macros for MCF_MDHA_MDCMR */
#define MCF_MDHA_MDCMR_SWR (0x00000001)
#define MCF_MDHA_MDCMR_RI (0x00000002)
#define MCF_MDHA_MDCMR_CI (0x00000004)
#define MCF_MDHA_MDCMR_GO (0x00000008)
/* Bit definitions and macros for MCF_MDHA_MDSR */
#define MCF_MDHA_MDSR_INT (0x00000001)
#define MCF_MDHA_MDSR_DONE (0x00000002)
#define MCF_MDHA_MDSR_ERR (0x00000004)
#define MCF_MDHA_MDSR_RD (0x00000008)
#define MCF_MDHA_MDSR_BUSY (0x00000010)
#define MCF_MDHA_MDSR_END (0x00000020)
#define MCF_MDHA_MDSR_HSH (0x00000040)
#define MCF_MDHA_MDSR_GNW (0x00000080)
#define MCF_MDHA_MDSR_FS(x) (((x)&0x00000007)<<8)
#define MCF_MDHA_MDSR_APD(x) (((x)&0x00000007)<<13)
#define MCF_MDHA_MDSR_IFL(x) (((x)&0x000000FF)<<16)
/* Bit definitions and macros for MCF_MDHA_MDIR */
#define MCF_MDHA_MDIR_IFO (0x00000001)
#define MCF_MDHA_MDIR_NON (0x00000004)
#define MCF_MDHA_MDIR_IME (0x00000010)
#define MCF_MDHA_MDIR_IDS (0x00000020)
#define MCF_MDHA_MDIR_RMDP (0x00000080)
#define MCF_MDHA_MDIR_ERE (0x00000100)
#define MCF_MDHA_MDIR_GTDS (0x00000200)
/* Bit definitions and macros for MCF_MDHA_MDIMR */
#define MCF_MDHA_MDIMR_IFO (0x00000001)
#define MCF_MDHA_MDIMR_NON (0x00000004)
#define MCF_MDHA_MDIMR_IME (0x00000010)
#define MCF_MDHA_MDIMR_IDS (0x00000020)
#define MCF_MDHA_MDIMR_RMDP (0x00000080)
#define MCF_MDHA_MDIMR_ERE (0x00000100)
#define MCF_MDHA_MDIMR_GTDS (0x00000200)
/* Bit definitions and macros for MCF_MDHA_MDDSR */
#define MCF_MDHA_MDDSR_DATASIZE(x) (((x)&0x1FFFFFFF)<<0)
/********************************************************************/
#endif /* __MCF523X_MDHA_H__ */

View File

@@ -0,0 +1,83 @@
/*
* File: mcf523x_pit.h
* Purpose: Register and bit definitions for the MCF523X
*
* Notes:
*
*/
#ifndef __MCF523X_PIT_H__
#define __MCF523X_PIT_H__
/*********************************************************************
*
* Programmable Interrupt Timer Modules (PIT)
*
*********************************************************************/
/* Register read/write macros */
#define MCF_PIT_PCSR0 (*(vuint16*)(void*)(&__IPSBAR[0x150000]))
#define MCF_PIT_PMR0 (*(vuint16*)(void*)(&__IPSBAR[0x150002]))
#define MCF_PIT_PCNTR0 (*(vuint16*)(void*)(&__IPSBAR[0x150004]))
#define MCF_PIT_PCSR1 (*(vuint16*)(void*)(&__IPSBAR[0x160000]))
#define MCF_PIT_PMR1 (*(vuint16*)(void*)(&__IPSBAR[0x160002]))
#define MCF_PIT_PCNTR1 (*(vuint16*)(void*)(&__IPSBAR[0x160004]))
#define MCF_PIT_PCSR2 (*(vuint16*)(void*)(&__IPSBAR[0x170000]))
#define MCF_PIT_PMR2 (*(vuint16*)(void*)(&__IPSBAR[0x170002]))
#define MCF_PIT_PCNTR2 (*(vuint16*)(void*)(&__IPSBAR[0x170004]))
#define MCF_PIT_PCSR3 (*(vuint16*)(void*)(&__IPSBAR[0x180000]))
#define MCF_PIT_PMR3 (*(vuint16*)(void*)(&__IPSBAR[0x180002]))
#define MCF_PIT_PCNTR3 (*(vuint16*)(void*)(&__IPSBAR[0x180004]))
#define MCF_PIT_PCSR(x) (*(vuint16*)(void*)(&__IPSBAR[0x150000+((x)*0x10000)]))
#define MCF_PIT_PMR(x) (*(vuint16*)(void*)(&__IPSBAR[0x150002+((x)*0x10000)]))
#define MCF_PIT_PCNTR(x) (*(vuint16*)(void*)(&__IPSBAR[0x150004+((x)*0x10000)]))
/* Bit definitions and macros for MCF_PIT_PCSR */
#define MCF_PIT_PCSR_EN (0x0001)
#define MCF_PIT_PCSR_RLD (0x0002)
#define MCF_PIT_PCSR_PIF (0x0004)
#define MCF_PIT_PCSR_PIE (0x0008)
#define MCF_PIT_PCSR_OVW (0x0010)
#define MCF_PIT_PCSR_HALTED (0x0020)
#define MCF_PIT_PCSR_DOZE (0x0040)
#define MCF_PIT_PCSR_PRE(x) (((x)&0x000F)<<8)
/* Bit definitions and macros for MCF_PIT_PMR */
#define MCF_PIT_PMR_PM0 (0x0001)
#define MCF_PIT_PMR_PM1 (0x0002)
#define MCF_PIT_PMR_PM2 (0x0004)
#define MCF_PIT_PMR_PM3 (0x0008)
#define MCF_PIT_PMR_PM4 (0x0010)
#define MCF_PIT_PMR_PM5 (0x0020)
#define MCF_PIT_PMR_PM6 (0x0040)
#define MCF_PIT_PMR_PM7 (0x0080)
#define MCF_PIT_PMR_PM8 (0x0100)
#define MCF_PIT_PMR_PM9 (0x0200)
#define MCF_PIT_PMR_PM10 (0x0400)
#define MCF_PIT_PMR_PM11 (0x0800)
#define MCF_PIT_PMR_PM12 (0x1000)
#define MCF_PIT_PMR_PM13 (0x2000)
#define MCF_PIT_PMR_PM14 (0x4000)
#define MCF_PIT_PMR_PM15 (0x8000)
/* Bit definitions and macros for MCF_PIT_PCNTR */
#define MCF_PIT_PCNTR_PC0 (0x0001)
#define MCF_PIT_PCNTR_PC1 (0x0002)
#define MCF_PIT_PCNTR_PC2 (0x0004)
#define MCF_PIT_PCNTR_PC3 (0x0008)
#define MCF_PIT_PCNTR_PC4 (0x0010)
#define MCF_PIT_PCNTR_PC5 (0x0020)
#define MCF_PIT_PCNTR_PC6 (0x0040)
#define MCF_PIT_PCNTR_PC7 (0x0080)
#define MCF_PIT_PCNTR_PC8 (0x0100)
#define MCF_PIT_PCNTR_PC9 (0x0200)
#define MCF_PIT_PCNTR_PC10 (0x0400)
#define MCF_PIT_PCNTR_PC11 (0x0800)
#define MCF_PIT_PCNTR_PC12 (0x1000)
#define MCF_PIT_PCNTR_PC13 (0x2000)
#define MCF_PIT_PCNTR_PC14 (0x4000)
#define MCF_PIT_PCNTR_PC15 (0x8000)
/********************************************************************/
#endif /* __MCF523X_PIT_H__ */

View File

@@ -0,0 +1,63 @@
/*
* File: mcf523x_qspi.h
* Purpose: Register and bit definitions for the MCF523X
*
* Notes:
*
*/
#ifndef __MCF523X_QSPI_H__
#define __MCF523X_QSPI_H__
/*********************************************************************
*
* Queued Serial Peripheral Interface (QSPI)
*
*********************************************************************/
/* Register read/write macros */
#define MCF_QSPI_QMR (*(vuint16*)(void*)(&__IPSBAR[0x000340]))
#define MCF_QSPI_QDLYR (*(vuint16*)(void*)(&__IPSBAR[0x000344]))
#define MCF_QSPI_QWR (*(vuint16*)(void*)(&__IPSBAR[0x000348]))
#define MCF_QSPI_QIR (*(vuint16*)(void*)(&__IPSBAR[0x00034C]))
#define MCF_QSPI_QAR (*(vuint16*)(void*)(&__IPSBAR[0x000350]))
#define MCF_QSPI_QDR (*(vuint16*)(void*)(&__IPSBAR[0x000354]))
/* Bit definitions and macros for MCF_QSPI_QMR */
#define MCF_QSPI_QMR_BAUD(x) (((x)&0x00FF)<<0)
#define MCF_QSPI_QMR_CPHA (0x0100)
#define MCF_QSPI_QMR_CPOL (0x0200)
#define MCF_QSPI_QMR_BITS(x) (((x)&0x000F)<<10)
#define MCF_QSPI_QMR_DOHIE (0x4000)
#define MCF_QSPI_QMR_MSTR (0x8000)
/* Bit definitions and macros for MCF_QSPI_QDLYR */
#define MCF_QSPI_QDLYR_DTL(x) (((x)&0x00FF)<<0)
#define MCF_QSPI_QDLYR_QCD(x) (((x)&0x007F)<<8)
#define MCF_QSPI_QDLYR_SPE (0x8000)
/* Bit definitions and macros for MCF_QSPI_QWR */
#define MCF_QSPI_QWR_NEWQP(x) (((x)&0x000F)<<0)
#define MCF_QSPI_QWR_ENDQP(x) (((x)&0x000F)<<8)
#define MCF_QSPI_QWR_CSIV (0x1000)
#define MCF_QSPI_QWR_WRTO (0x2000)
#define MCF_QSPI_QWR_WREN (0x4000)
#define MCF_QSPI_QWR_HALT (0x8000)
/* Bit definitions and macros for MCF_QSPI_QIR */
#define MCF_QSPI_QIR_SPIF (0x0001)
#define MCF_QSPI_QIR_ABRT (0x0004)
#define MCF_QSPI_QIR_WCEF (0x0008)
#define MCF_QSPI_QIR_SPIFE (0x0100)
#define MCF_QSPI_QIR_ABRTE (0x0400)
#define MCF_QSPI_QIR_WCEFE (0x0800)
#define MCF_QSPI_QIR_ABRTL (0x1000)
#define MCF_QSPI_QIR_ABRTB (0x4000)
#define MCF_QSPI_QIR_WCEFB (0x8000)
/* Bit definitions and macros for MCF_QSPI_QAR */
#define MCF_QSPI_QAR_ADDR(x) (((x)&0x003F)<<0)
/********************************************************************/
#endif /* __MCF523X_QSPI_H__ */

View File

@@ -0,0 +1,36 @@
/*
* File: mcf523x_rcm.h
* Purpose: Register and bit definitions for the MCF523X
*
* Notes:
*
*/
#ifndef __MCF523X_RCM_H__
#define __MCF523X_RCM_H__
/*********************************************************************
*
* Reset Configuration Module (RCM)
*
*********************************************************************/
/* Register read/write macros */
#define MCF_RCM_RCR (*(vuint8 *)(void*)(&__IPSBAR[0x110000]))
#define MCF_RCM_RSR (*(vuint8 *)(void*)(&__IPSBAR[0x110001]))
/* Bit definitions and macros for MCF_RCM_RCR */
#define MCF_RCM_RCR_FRCRSTOUT (0x40)
#define MCF_RCM_RCR_SOFTRST (0x80)
/* Bit definitions and macros for MCF_RCM_RSR */
#define MCF_RCM_RSR_LOL (0x01)
#define MCF_RCM_RSR_LOC (0x02)
#define MCF_RCM_RSR_EXT (0x04)
#define MCF_RCM_RSR_POR (0x08)
#define MCF_RCM_RSR_WDR (0x10)
#define MCF_RCM_RSR_SOFT (0x20)
/********************************************************************/
#endif /* __MCF523X_RCM_H__ */

View File

@@ -0,0 +1,40 @@
/*
* File: mcf523x_rng.h
* Purpose: Register and bit definitions for the MCF523X
*
* Notes:
*
*/
#ifndef __MCF523X_RNG_H__
#define __MCF523X_RNG_H__
/*********************************************************************
*
* Random Number Generator (RNG)
*
*********************************************************************/
/* Register read/write macros */
#define MCF_RNG_RNGCR (*(vuint32*)(void*)(&__IPSBAR[0x1A0000]))
#define MCF_RNG_RNGSR (*(vuint32*)(void*)(&__IPSBAR[0x1A0004]))
#define MCF_RNG_RNGER (*(vuint32*)(void*)(&__IPSBAR[0x1A0008]))
#define MCF_RNG_RNGOUT (*(vuint32*)(void*)(&__IPSBAR[0x1A000C]))
/* Bit definitions and macros for MCF_RNG_RNGCR */
#define MCF_RNG_RNGCR_GO (0x00000001)
#define MCF_RNG_RNGCR_HA (0x00000002)
#define MCF_RNG_RNGCR_IM (0x00000004)
#define MCF_RNG_RNGCR_CI (0x00000008)
/* Bit definitions and macros for MCF_RNG_RNGSR */
#define MCF_RNG_RNGSR_SV (0x00000001)
#define MCF_RNG_RNGSR_LRS (0x00000002)
#define MCF_RNG_RNGSR_FUF (0x00000004)
#define MCF_RNG_RNGSR_EI (0x00000008)
#define MCF_RNG_RNGSR_OFL(x) (((x)&0x000000FF)<<8)
#define MCF_RNG_RNGSR_OFS(x) (((x)&0x000000FF)<<16)
/********************************************************************/
#endif /* __MCF523X_RNG_H__ */

View File

@@ -0,0 +1,144 @@
/*
* File: mcf523x_scm.h
* Purpose: Register and bit definitions for the MCF523X
*
* Notes:
*
*/
#ifndef __MCF523X_SCM_H__
#define __MCF523X_SCM_H__
/*********************************************************************
*
* System Control Module (SCM)
*
*********************************************************************/
/* Register read/write macros */
#define MCF_SCM_IPSBAR (*(vuint32*)(void*)(&__IPSBAR[0x000000]))
#define MCF_SCM_RAMBAR (*(vuint32*)(void*)(&__IPSBAR[0x000008]))
#define MCF_SCM_CRSR (*(vuint8 *)(void*)(&__IPSBAR[0x000010]))
#define MCF_SCM_CWCR (*(vuint8 *)(void*)(&__IPSBAR[0x000011]))
#define MCF_SCM_LPICR (*(vuint8 *)(void*)(&__IPSBAR[0x000012]))
#define MCF_SCM_CWSR (*(vuint8 *)(void*)(&__IPSBAR[0x000013]))
#define MCF_SCM_DMAREQC (*(vuint32*)(void*)(&__IPSBAR[0x000014]))
#define MCF_SCM_MPARK (*(vuint32*)(void*)(&__IPSBAR[0x00001C]))
#define MCF_SCM_MPR (*(vuint8 *)(void*)(&__IPSBAR[0x000020]))
#define MCF_SCM_PACR0 (*(vuint8 *)(void*)(&__IPSBAR[0x000024]))
#define MCF_SCM_PACR1 (*(vuint8 *)(void*)(&__IPSBAR[0x000025]))
#define MCF_SCM_PACR2 (*(vuint8 *)(void*)(&__IPSBAR[0x000026]))
#define MCF_SCM_PACR3 (*(vuint8 *)(void*)(&__IPSBAR[0x000027]))
#define MCF_SCM_PACR4 (*(vuint8 *)(void*)(&__IPSBAR[0x000028]))
#define MCF_SCM_PACR5 (*(vuint8 *)(void*)(&__IPSBAR[0x00002A]))
#define MCF_SCM_PACR6 (*(vuint8 *)(void*)(&__IPSBAR[0x00002B]))
#define MCF_SCM_PACR7 (*(vuint8 *)(void*)(&__IPSBAR[0x00002C]))
#define MCF_SCM_PACR8 (*(vuint8 *)(void*)(&__IPSBAR[0x00002E]))
#define MCF_SCM_GPACR0 (*(vuint8 *)(void*)(&__IPSBAR[0x000030]))
/* Bit definitions and macros for MCF_SCM_IPSBAR */
#define MCF_SCM_IPSBAR_V (0x00000001)
#define MCF_SCM_IPSBAR_BA(x) (((x)&0x00000003)<<30)
/* Bit definitions and macros for MCF_SCM_RAMBAR */
#define MCF_SCM_RAMBAR_BDE (0x00000200)
#define MCF_SCM_RAMBAR_BA(x) (((x)&0x0000FFFF)<<16)
/* Bit definitions and macros for MCF_SCM_CRSR */
#define MCF_SCM_CRSR_CWDR (0x20)
#define MCF_SCM_CRSR_EXT (0x80)
/* Bit definitions and macros for MCF_SCM_CWCR */
#define MCF_SCM_CWCR_CWTIC (0x01)
#define MCF_SCM_CWCR_CWTAVAL (0x02)
#define MCF_SCM_CWCR_CWTA (0x04)
#define MCF_SCM_CWCR_CWT(x) (((x)&0x07)<<3)
#define MCF_SCM_CWCR_CWRI (0x40)
#define MCF_SCM_CWCR_CWE (0x80)
/* Bit definitions and macros for MCF_SCM_LPICR */
#define MCF_SCM_LPICR_XLPM_IPL(x) (((x)&0x07)<<4)
#define MCF_SCM_LPICR_ENBSTOP (0x80)
/* Bit definitions and macros for MCF_SCM_DMAREQC */
#define MCF_SCM_DMAREQC_DMAC0(x) (((x)&0x0000000F)<<0)
#define MCF_SCM_DMAREQC_DMAC1(x) (((x)&0x0000000F)<<4)
#define MCF_SCM_DMAREQC_DMAC2(x) (((x)&0x0000000F)<<8)
#define MCF_SCM_DMAREQC_DMAC3(x) (((x)&0x0000000F)<<12)
/* Bit definitions and macros for MCF_SCM_MPARK */
#define MCF_SCM_MPARK_LCKOUT_TIME(x) (((x)&0x0000000F)<<8)
#define MCF_SCM_MPARK_PRKLAST (0x00001000)
#define MCF_SCM_MPARK_TIMEOUT (0x00002000)
#define MCF_SCM_MPARK_FIXED (0x00004000)
#define MCF_SCM_MPARK_M1_PRTY(x) (((x)&0x00000003)<<16)
#define MCF_SCM_MPARK_M0_PRTY(x) (((x)&0x00000003)<<18)
#define MCF_SCM_MPARK_M2_PRTY(x) (((x)&0x00000003)<<20)
#define MCF_SCM_MPARK_M3_PRTY(x) (((x)&0x00000003)<<22)
#define MCF_SCM_MPARK_BCR24BIT (0x01000000)
#define MCF_SCM_MPARK_M2_P_EN (0x02000000)
/* Bit definitions and macros for MCF_SCM_MPR */
#define MCF_SCM_MPR_MPR(x) (((x)&0x0F)<<0)
/* Bit definitions and macros for MCF_SCM_PACR0 */
#define MCF_SCM_PACR0_ACCESS_CTRL0(x) (((x)&0x07)<<0)
#define MCF_SCM_PACR0_LOCK0 (0x08)
#define MCF_SCM_PACR0_ACCESS_CTRL1(x) (((x)&0x07)<<4)
#define MCF_SCM_PACR0_LOCK1 (0x80)
/* Bit definitions and macros for MCF_SCM_PACR1 */
#define MCF_SCM_PACR1_ACCESS_CTRL0(x) (((x)&0x07)<<0)
#define MCF_SCM_PACR1_LOCK0 (0x08)
#define MCF_SCM_PACR1_ACCESS_CTRL1(x) (((x)&0x07)<<4)
#define MCF_SCM_PACR1_LOCK1 (0x80)
/* Bit definitions and macros for MCF_SCM_PACR2 */
#define MCF_SCM_PACR2_ACCESS_CTRL0(x) (((x)&0x07)<<0)
#define MCF_SCM_PACR2_LOCK0 (0x08)
#define MCF_SCM_PACR2_ACCESS_CTRL1(x) (((x)&0x07)<<4)
#define MCF_SCM_PACR2_LOCK1 (0x80)
/* Bit definitions and macros for MCF_SCM_PACR3 */
#define MCF_SCM_PACR3_ACCESS_CTRL0(x) (((x)&0x07)<<0)
#define MCF_SCM_PACR3_LOCK0 (0x08)
#define MCF_SCM_PACR3_ACCESS_CTRL1(x) (((x)&0x07)<<4)
#define MCF_SCM_PACR3_LOCK1 (0x80)
/* Bit definitions and macros for MCF_SCM_PACR4 */
#define MCF_SCM_PACR4_ACCESS_CTRL0(x) (((x)&0x07)<<0)
#define MCF_SCM_PACR4_LOCK0 (0x08)
#define MCF_SCM_PACR4_ACCESS_CTRL1(x) (((x)&0x07)<<4)
#define MCF_SCM_PACR4_LOCK1 (0x80)
/* Bit definitions and macros for MCF_SCM_PACR5 */
#define MCF_SCM_PACR5_ACCESS_CTRL0(x) (((x)&0x07)<<0)
#define MCF_SCM_PACR5_LOCK0 (0x08)
#define MCF_SCM_PACR5_ACCESS_CTRL1(x) (((x)&0x07)<<4)
#define MCF_SCM_PACR5_LOCK1 (0x80)
/* Bit definitions and macros for MCF_SCM_PACR6 */
#define MCF_SCM_PACR6_ACCESS_CTRL0(x) (((x)&0x07)<<0)
#define MCF_SCM_PACR6_LOCK0 (0x08)
#define MCF_SCM_PACR6_ACCESS_CTRL1(x) (((x)&0x07)<<4)
#define MCF_SCM_PACR6_LOCK1 (0x80)
/* Bit definitions and macros for MCF_SCM_PACR7 */
#define MCF_SCM_PACR7_ACCESS_CTRL0(x) (((x)&0x07)<<0)
#define MCF_SCM_PACR7_LOCK0 (0x08)
#define MCF_SCM_PACR7_ACCESS_CTRL1(x) (((x)&0x07)<<4)
#define MCF_SCM_PACR7_LOCK1 (0x80)
/* Bit definitions and macros for MCF_SCM_PACR8 */
#define MCF_SCM_PACR8_ACCESS_CTRL0(x) (((x)&0x07)<<0)
#define MCF_SCM_PACR8_LOCK0 (0x08)
#define MCF_SCM_PACR8_ACCESS_CTRL1(x) (((x)&0x07)<<4)
#define MCF_SCM_PACR8_LOCK1 (0x80)
/* Bit definitions and macros for MCF_SCM_GPACR0 */
#define MCF_SCM_GPACR0_ACCESS_CTRL(x) (((x)&0x0F)<<0)
#define MCF_SCM_GPACR0_LOCK (0x80)
/********************************************************************/
#endif /* __MCF523X_SCM_H__ */

View File

@@ -0,0 +1,88 @@
/*
* File: mcf523x_sdramc.h
* Purpose: Register and bit definitions for the MCF523X
*
* Notes:
*
*/
#ifndef __MCF523X_SDRAMC_H__
#define __MCF523X_SDRAMC_H__
/*********************************************************************
*
* SDRAM Controller (SDRAMC)
*
*********************************************************************/
/* Register read/write macros */
#define MCF_SDRAMC_DCR (*(vuint16*)(void*)(&__IPSBAR[0x000040]))
#define MCF_SDRAMC_DACR0 (*(vuint32*)(void*)(&__IPSBAR[0x000048]))
#define MCF_SDRAMC_DMR0 (*(vuint32*)(void*)(&__IPSBAR[0x00004C]))
#define MCF_SDRAMC_DACR1 (*(vuint32*)(void*)(&__IPSBAR[0x000050]))
#define MCF_SDRAMC_DMR1 (*(vuint32*)(void*)(&__IPSBAR[0x000054]))
/* Bit definitions and macros for MCF_SDRAMC_DCR */
#define MCF_SDRAMC_DCR_RC(x) (((x)&0x01FF)<<0)
#define MCF_SDRAMC_DCR_RTIM(x) (((x)&0x0003)<<9)
#define MCF_SDRAMC_DCR_IS (0x0800)
#define MCF_SDRAMC_DCR_COC (0x1000)
#define MCF_SDRAMC_DCR_NAM (0x2000)
/* Bit definitions and macros for MCF_SDRAMC_DACR0 */
#define MCF_SDRAMC_DACR0_IP (0x00000008)
#define MCF_SDRAMC_DACR0_PS(x) (((x)&0x00000003)<<4)
#define MCF_SDRAMC_DACR0_MRS (0x00000040)
#define MCF_SDRAMC_DACR0_CBM(x) (((x)&0x00000007)<<8)
#define MCF_SDRAMC_DACR0_CASL(x) (((x)&0x00000003)<<12)
#define MCF_SDRAMC_DACR0_RE (0x00008000)
#define MCF_SDRAMC_DACR0_BA(x) (((x)&0x00003FFF)<<18)
/* Bit definitions and macros for MCF_SDRAMC_DMR0 */
#define MCF_SDRAMC_DMR0_V (0x00000001)
#define MCF_SDRAMC_DMR0_WP (0x00000100)
#define MCF_SDRAMC_DMR0_BAM(x) (((x)&0x00003FFF)<<18)
/* Bit definitions and macros for MCF_SDRAMC_DACR1 */
#define MCF_SDRAMC_DACR1_IP (0x00000008)
#define MCF_SDRAMC_DACR1_PS(x) (((x)&0x00000003)<<4)
#define MCF_SDRAMC_DACR1_MRS (0x00000040)
#define MCF_SDRAMC_DACR1_CBM(x) (((x)&0x00000007)<<8)
#define MCF_SDRAMC_DACR1_CASL(x) (((x)&0x00000003)<<12)
#define MCF_SDRAMC_DACR1_RE (0x00008000)
#define MCF_SDRAMC_DACR1_BA(x) (((x)&0x00003FFF)<<18)
/* Bit definitions and macros for MCF_SDRAMC_DMR1 */
#define MCF_SDRAMC_DMR1_V (0x00000001)
#define MCF_SDRAMC_DMR1_WP (0x00000100)
#define MCF_SDRAMC_DMR1_BAM(x) (((x)&0x00003FFF)<<18)
/********************************************************************/
#define MCF_SDRAMC_DMR_BAM_4G (0xFFFC0000)
#define MCF_SDRAMC_DMR_BAM_2G (0x7FFC0000)
#define MCF_SDRAMC_DMR_BAM_1G (0x3FFC0000)
#define MCF_SDRAMC_DMR_BAM_1024M (0x3FFC0000)
#define MCF_SDRAMC_DMR_BAM_512M (0x1FFC0000)
#define MCF_SDRAMC_DMR_BAM_256M (0x0FFC0000)
#define MCF_SDRAMC_DMR_BAM_128M (0x07FC0000)
#define MCF_SDRAMC_DMR_BAM_64M (0x03FC0000)
#define MCF_SDRAMC_DMR_BAM_32M (0x01FC0000)
#define MCF_SDRAMC_DMR_BAM_16M (0x00FC0000)
#define MCF_SDRAMC_DMR_BAM_8M (0x007C0000)
#define MCF_SDRAMC_DMR_BAM_4M (0x003C0000)
#define MCF_SDRAMC_DMR_BAM_2M (0x001C0000)
#define MCF_SDRAMC_DMR_BAM_1M (0x000C0000)
#define MCF_SDRAMC_DMR_BAM_1024K (0x000C0000)
#define MCF_SDRAMC_DMR_BAM_512K (0x00040000)
#define MCF_SDRAMC_DMR_BAM_256K (0x00000000)
#define MCF_SDRAMC_DMR_WP (0x00000100)
#define MCF_SDRAMC_DMR_CI (0x00000040)
#define MCF_SDRAMC_DMR_AM (0x00000020)
#define MCF_SDRAMC_DMR_SC (0x00000010)
#define MCF_SDRAMC_DMR_SD (0x00000008)
#define MCF_SDRAMC_DMR_UC (0x00000004)
#define MCF_SDRAMC_DMR_UD (0x00000002)
#define MCF_SDRAMC_DMR_V (0x00000001)
#endif /* __MCF523X_SDRAMC_H__ */

View File

@@ -0,0 +1,114 @@
/*
* File: mcf523x_skha.h
* Purpose: Register and bit definitions for the MCF523X
*
* Notes:
*
*/
#ifndef __MCF523X_SKHA_H__
#define __MCF523X_SKHA_H__
/*********************************************************************
*
* Symmetric Key Hardware Accelerator (SKHA)
*
*********************************************************************/
/* Register read/write macros */
#define MCF_SKHA_SKMR (*(vuint32*)(void*)(&__IPSBAR[0x1B0000]))
#define MCF_SKHA_SKCR (*(vuint32*)(void*)(&__IPSBAR[0x1B0004]))
#define MCF_SKHA_SKCMR (*(vuint32*)(void*)(&__IPSBAR[0x1B0008]))
#define MCF_SKHA_SKSR (*(vuint32*)(void*)(&__IPSBAR[0x1B000C]))
#define MCF_SKHA_SKIR (*(vuint32*)(void*)(&__IPSBAR[0x1B0010]))
#define MCF_SKHA_SKIMR (*(vuint32*)(void*)(&__IPSBAR[0x1B0014]))
#define MCF_SKHA_SKKSR (*(vuint32*)(void*)(&__IPSBAR[0x1B0018]))
#define MCF_SKHA_SKDSR (*(vuint32*)(void*)(&__IPSBAR[0x1B001C]))
#define MCF_SKHA_SKIN (*(vuint32*)(void*)(&__IPSBAR[0x1B0020]))
#define MCF_SKHA_SKOUT (*(vuint32*)(void*)(&__IPSBAR[0x1B0024]))
#define MCF_SKHA_SKKDR0 (*(vuint32*)(void*)(&__IPSBAR[0x1B0030]))
#define MCF_SKHA_SKKDR1 (*(vuint32*)(void*)(&__IPSBAR[0x1B0034]))
#define MCF_SKHA_SKKDR2 (*(vuint32*)(void*)(&__IPSBAR[0x1B0038]))
#define MCF_SKHA_SKKDR3 (*(vuint32*)(void*)(&__IPSBAR[0x1B003C]))
#define MCF_SKHA_SKKDR4 (*(vuint32*)(void*)(&__IPSBAR[0x1B0040]))
#define MCF_SKHA_SKKDR5 (*(vuint32*)(void*)(&__IPSBAR[0x1B0044]))
#define MCF_SKHA_SKKDRn(x) (*(vuint32*)(void*)(&__IPSBAR[0x1B0030+((x)*0x004)]))
#define MCF_SKHA_SKCR0 (*(vuint32*)(void*)(&__IPSBAR[0x1B0070]))
#define MCF_SKHA_SKCR1 (*(vuint32*)(void*)(&__IPSBAR[0x1B0074]))
#define MCF_SKHA_SKCR2 (*(vuint32*)(void*)(&__IPSBAR[0x1B0078]))
#define MCF_SKHA_SKCR3 (*(vuint32*)(void*)(&__IPSBAR[0x1B007C]))
#define MCF_SKHA_SKCR4 (*(vuint32*)(void*)(&__IPSBAR[0x1B0080]))
#define MCF_SKHA_SKCR5 (*(vuint32*)(void*)(&__IPSBAR[0x1B0084]))
#define MCF_SKHA_SKCR6 (*(vuint32*)(void*)(&__IPSBAR[0x1B0088]))
#define MCF_SKHA_SKCR7 (*(vuint32*)(void*)(&__IPSBAR[0x1B008C]))
#define MCF_SKHA_SKCR8 (*(vuint32*)(void*)(&__IPSBAR[0x1B0090]))
#define MCF_SKHA_SKCR9 (*(vuint32*)(void*)(&__IPSBAR[0x1B0094]))
#define MCF_SKHA_SKCR10 (*(vuint32*)(void*)(&__IPSBAR[0x1B0098]))
#define MCF_SKHA_SKCR11 (*(vuint32*)(void*)(&__IPSBAR[0x1B009C]))
#define MCF_SKHA_SKCRn(x) (*(vuint32*)(void*)(&__IPSBAR[0x1B0070+((x)*0x004)]))
/* Bit definitions and macros for MCF_SKHA_SKMR */
#define MCF_SKHA_SKMR_ALG(x) (((x)&0x00000003)<<0)
#define MCF_SKHA_SKMR_DIR (0x00000004)
#define MCF_SKHA_SKMR_CM(x) (((x)&0x00000003)<<3)
#define MCF_SKHA_SKMR_DKP (0x00000100)
#define MCF_SKHA_SKMR_CTRM(x) (((x)&0x0000000F)<<9)
#define MCF_SKHA_SKMR_CM_ECB (0x00000000)
#define MCF_SKHA_SKMR_CM_CBC (0x00000008)
#define MCF_SKHA_SKMR_CM_CTR (0x00000018)
#define MCF_SKHA_SKMR_DIR_DEC (0x00000000)
#define MCF_SKHA_SKMR_DIR_ENC (0x00000004)
#define MCF_SKHA_SKMR_ALG_AES (0x00000000)
#define MCF_SKHA_SKMR_ALG_DES (0x00000001)
#define MCF_SKHA_SKMR_ALG_TDES (0x00000002)
/* Bit definitions and macros for MCF_SKHA_SKCR */
#define MCF_SKHA_SKCR_IE (0x00000001)
/* Bit definitions and macros for MCF_SKHA_SKCMR */
#define MCF_SKHA_SKCMR_SWR (0x00000001)
#define MCF_SKHA_SKCMR_RI (0x00000002)
#define MCF_SKHA_SKCMR_CI (0x00000004)
#define MCF_SKHA_SKCMR_GO (0x00000008)
/* Bit definitions and macros for MCF_SKHA_SKSR */
#define MCF_SKHA_SKSR_INT (0x00000001)
#define MCF_SKHA_SKSR_DONE (0x00000002)
#define MCF_SKHA_SKSR_ERR (0x00000004)
#define MCF_SKHA_SKSR_RD (0x00000008)
#define MCF_SKHA_SKSR_BUSY (0x00000010)
#define MCF_SKHA_SKSR_IFL(x) (((x)&0x000000FF)<<16)
#define MCF_SKHA_SKSR_OFL(x) (((x)&0x000000FF)<<24)
/* Bit definitions and macros for MCF_SKHA_SKIR */
#define MCF_SKHA_SKIR_IFO (0x00000001)
#define MCF_SKHA_SKIR_OFU (0x00000002)
#define MCF_SKHA_SKIR_NEIF (0x00000004)
#define MCF_SKHA_SKIR_NEOF (0x00000008)
#define MCF_SKHA_SKIR_IME (0x00000010)
#define MCF_SKHA_SKIR_DSE (0x00000020)
#define MCF_SKHA_SKIR_KSE (0x00000040)
#define MCF_SKHA_SKIR_RMDP (0x00000080)
#define MCF_SKHA_SKIR_ERE (0x00000100)
#define MCF_SKHA_SKIR_KPE (0x00000200)
#define MCF_SKHA_SKIR_KRE (0x00000400)
/* Bit definitions and macros for MCF_SKHA_SKIMR */
#define MCF_SKHA_SKIMR_IFO (0x00000001)
#define MCF_SKHA_SKIMR_OFU (0x00000002)
#define MCF_SKHA_SKIMR_NEIF (0x00000004)
#define MCF_SKHA_SKIMR_NEOF (0x00000008)
#define MCF_SKHA_SKIMR_IME (0x00000010)
#define MCF_SKHA_SKIMR_DSE (0x00000020)
#define MCF_SKHA_SKIMR_KSE (0x00000040)
#define MCF_SKHA_SKIMR_RMDP (0x00000080)
#define MCF_SKHA_SKIMR_ERE (0x00000100)
#define MCF_SKHA_SKIMR_KPE (0x00000200)
#define MCF_SKHA_SKIMR_KRE (0x00000400)
/* Bit definitions and macros for MCF_SKHA_SKKSR */
#define MCF_SKHA_SKKSR_KEYSIZE(x) (((x)&0x0000003F)<<0)
/********************************************************************/
#endif /* __MCF523X_SKHA_H__ */

View File

@@ -0,0 +1,36 @@
/*
* File: mcf523x_sram.h
* Purpose: Register and bit definitions for the MCF523X
*
* Notes:
*
*/
#ifndef __MCF523X_SRAM_H__
#define __MCF523X_SRAM_H__
/*********************************************************************
*
* 64KByte System SRAM (SRAM)
*
*********************************************************************/
/* Register read/write macros */
#define MCF_SRAM_RAMBAR (*(vuint32*)(void*)(&__IPSBAR[0x20000000]))
/* Bit definitions and macros for MCF_SRAM_RAMBAR */
#define MCF_SRAM_RAMBAR_V (0x00000001)
#define MCF_SRAM_RAMBAR_UD (0x00000002)
#define MCF_SRAM_RAMBAR_UC (0x00000004)
#define MCF_SRAM_RAMBAR_SD (0x00000008)
#define MCF_SRAM_RAMBAR_SC (0x00000010)
#define MCF_SRAM_RAMBAR_CI (0x00000020)
#define MCF_SRAM_RAMBAR_WP (0x00000100)
#define MCF_SRAM_RAMBAR_SPV (0x00000200)
#define MCF_SRAM_RAMBAR_PRI2 (0x00000400)
#define MCF_SRAM_RAMBAR_PRI1 (0x00000800)
#define MCF_SRAM_RAMBAR_BA(x) (((x)&0x0000FFFF)<<16)
/********************************************************************/
#endif /* __MCF523X_SRAM_H__ */

View File

@@ -0,0 +1,77 @@
/*
* File: mcf523x_timer.h
* Purpose: Register and bit definitions for the MCF523X
*
* Notes:
*
*/
#ifndef __MCF523X_TIMER_H__
#define __MCF523X_TIMER_H__
/*********************************************************************
*
* DMA Timers (TIMER)
*
*********************************************************************/
/* Register read/write macros */
#define MCF_TIMER_DTMR0 (*(vuint16*)(void*)(&__IPSBAR[0x000400]))
#define MCF_TIMER_DTXMR0 (*(vuint8 *)(void*)(&__IPSBAR[0x000402]))
#define MCF_TIMER_DTER0 (*(vuint8 *)(void*)(&__IPSBAR[0x000403]))
#define MCF_TIMER_DTRR0 (*(vuint32*)(void*)(&__IPSBAR[0x000404]))
#define MCF_TIMER_DTCR0 (*(vuint32*)(void*)(&__IPSBAR[0x000408]))
#define MCF_TIMER_DTCN0 (*(vuint32*)(void*)(&__IPSBAR[0x00040C]))
#define MCF_TIMER_DTMR1 (*(vuint16*)(void*)(&__IPSBAR[0x000440]))
#define MCF_TIMER_DTXMR1 (*(vuint8 *)(void*)(&__IPSBAR[0x000442]))
#define MCF_TIMER_DTER1 (*(vuint8 *)(void*)(&__IPSBAR[0x000443]))
#define MCF_TIMER_DTRR1 (*(vuint32*)(void*)(&__IPSBAR[0x000444]))
#define MCF_TIMER_DTCR1 (*(vuint32*)(void*)(&__IPSBAR[0x000448]))
#define MCF_TIMER_DTCN1 (*(vuint32*)(void*)(&__IPSBAR[0x00044C]))
#define MCF_TIMER_DTMR2 (*(vuint16*)(void*)(&__IPSBAR[0x000480]))
#define MCF_TIMER_DTXMR2 (*(vuint8 *)(void*)(&__IPSBAR[0x000482]))
#define MCF_TIMER_DTER2 (*(vuint8 *)(void*)(&__IPSBAR[0x000483]))
#define MCF_TIMER_DTRR2 (*(vuint32*)(void*)(&__IPSBAR[0x000484]))
#define MCF_TIMER_DTCR2 (*(vuint32*)(void*)(&__IPSBAR[0x000488]))
#define MCF_TIMER_DTCN2 (*(vuint32*)(void*)(&__IPSBAR[0x00048C]))
#define MCF_TIMER_DTMR3 (*(vuint16*)(void*)(&__IPSBAR[0x0004C0]))
#define MCF_TIMER_DTXMR3 (*(vuint8 *)(void*)(&__IPSBAR[0x0004C2]))
#define MCF_TIMER_DTER3 (*(vuint8 *)(void*)(&__IPSBAR[0x0004C3]))
#define MCF_TIMER_DTRR3 (*(vuint32*)(void*)(&__IPSBAR[0x0004C4]))
#define MCF_TIMER_DTCR3 (*(vuint32*)(void*)(&__IPSBAR[0x0004C8]))
#define MCF_TIMER_DTCN3 (*(vuint32*)(void*)(&__IPSBAR[0x0004CC]))
#define MCF_TIMER_DTMR(x) (*(vuint16*)(void*)(&__IPSBAR[0x000400+((x)*0x040)]))
#define MCF_TIMER_DTXMR(x) (*(vuint8 *)(void*)(&__IPSBAR[0x000402+((x)*0x040)]))
#define MCF_TIMER_DTER(x) (*(vuint8 *)(void*)(&__IPSBAR[0x000403+((x)*0x040)]))
#define MCF_TIMER_DTRR(x) (*(vuint32*)(void*)(&__IPSBAR[0x000404+((x)*0x040)]))
#define MCF_TIMER_DTCR(x) (*(vuint32*)(void*)(&__IPSBAR[0x000408+((x)*0x040)]))
#define MCF_TIMER_DTCN(x) (*(vuint32*)(void*)(&__IPSBAR[0x00040C+((x)*0x040)]))
/* Bit definitions and macros for MCF_TIMER_DTMR */
#define MCF_TIMER_DTMR_RST (0x0001)
#define MCF_TIMER_DTMR_CLK(x) (((x)&0x0003)<<1)
#define MCF_TIMER_DTMR_FRR (0x0008)
#define MCF_TIMER_DTMR_ORRI (0x0010)
#define MCF_TIMER_DTMR_OM (0x0020)
#define MCF_TIMER_DTMR_CE(x) (((x)&0x0003)<<6)
#define MCF_TIMER_DTMR_PS(x) (((x)&0x00FF)<<8)
#define MCF_TIMER_DTMR_CE_ANY (0x00C0)
#define MCF_TIMER_DTMR_CE_FALL (0x0080)
#define MCF_TIMER_DTMR_CE_RISE (0x0040)
#define MCF_TIMER_DTMR_CE_NONE (0x0000)
#define MCF_TIMER_DTMR_CLK_DTIN (0x0006)
#define MCF_TIMER_DTMR_CLK_DIV16 (0x0004)
#define MCF_TIMER_DTMR_CLK_DIV1 (0x0002)
#define MCF_TIMER_DTMR_CLK_STOP (0x0000)
/* Bit definitions and macros for MCF_TIMER_DTXMR */
#define MCF_TIMER_DTXMR_MODE16 (0x01)
#define MCF_TIMER_DTXMR_DMAEN (0x80)
/* Bit definitions and macros for MCF_TIMER_DTER */
#define MCF_TIMER_DTER_CAP (0x01)
#define MCF_TIMER_DTER_REF (0x02)
/********************************************************************/
#endif /* __MCF523X_TIMER_H__ */

View File

@@ -0,0 +1,180 @@
/*
* File: mcf523x_uart.h
* Purpose: Register and bit definitions for the MCF523X
*
* Notes:
*
*/
#ifndef __MCF523X_UART_H__
#define __MCF523X_UART_H__
/*********************************************************************
*
* Universal Asynchronous Receiver Transmitter (UART)
*
*********************************************************************/
/* Register read/write macros */
#define MCF_UART_UMR0 (*(vuint8 *)(void*)(&__IPSBAR[0x000200]))
#define MCF_UART_USR0 (*(vuint8 *)(void*)(&__IPSBAR[0x000204]))
#define MCF_UART_UCSR0 (*(vuint8 *)(void*)(&__IPSBAR[0x000204]))
#define MCF_UART_UCR0 (*(vuint8 *)(void*)(&__IPSBAR[0x000208]))
#define MCF_UART_URB0 (*(vuint8 *)(void*)(&__IPSBAR[0x00020C]))
#define MCF_UART_UTB0 (*(vuint8 *)(void*)(&__IPSBAR[0x00020C]))
#define MCF_UART_UIPCR0 (*(vuint8 *)(void*)(&__IPSBAR[0x000210]))
#define MCF_UART_UACR0 (*(vuint8 *)(void*)(&__IPSBAR[0x000210]))
#define MCF_UART_UISR0 (*(vuint8 *)(void*)(&__IPSBAR[0x000214]))
#define MCF_UART_UIMR0 (*(vuint8 *)(void*)(&__IPSBAR[0x000214]))
#define MCF_UART_UBG10 (*(vuint8 *)(void*)(&__IPSBAR[0x000218]))
#define MCF_UART_UBG20 (*(vuint8 *)(void*)(&__IPSBAR[0x00021C]))
#define MCF_UART_UIP0 (*(vuint8 *)(void*)(&__IPSBAR[0x000234]))
#define MCF_UART_UOP10 (*(vuint8 *)(void*)(&__IPSBAR[0x000238]))
#define MCF_UART_UOP00 (*(vuint8 *)(void*)(&__IPSBAR[0x00023C]))
#define MCF_UART_UMR1 (*(vuint8 *)(void*)(&__IPSBAR[0x000240]))
#define MCF_UART_USR1 (*(vuint8 *)(void*)(&__IPSBAR[0x000244]))
#define MCF_UART_UCSR1 (*(vuint8 *)(void*)(&__IPSBAR[0x000244]))
#define MCF_UART_UCR1 (*(vuint8 *)(void*)(&__IPSBAR[0x000248]))
#define MCF_UART_URB1 (*(vuint8 *)(void*)(&__IPSBAR[0x00024C]))
#define MCF_UART_UTB1 (*(vuint8 *)(void*)(&__IPSBAR[0x00024C]))
#define MCF_UART_UIPCR1 (*(vuint8 *)(void*)(&__IPSBAR[0x000250]))
#define MCF_UART_UACR1 (*(vuint8 *)(void*)(&__IPSBAR[0x000250]))
#define MCF_UART_UISR1 (*(vuint8 *)(void*)(&__IPSBAR[0x000254]))
#define MCF_UART_UIMR1 (*(vuint8 *)(void*)(&__IPSBAR[0x000254]))
#define MCF_UART_UBG11 (*(vuint8 *)(void*)(&__IPSBAR[0x000258]))
#define MCF_UART_UBG21 (*(vuint8 *)(void*)(&__IPSBAR[0x00025C]))
#define MCF_UART_UIP1 (*(vuint8 *)(void*)(&__IPSBAR[0x000274]))
#define MCF_UART_UOP11 (*(vuint8 *)(void*)(&__IPSBAR[0x000278]))
#define MCF_UART_UOP01 (*(vuint8 *)(void*)(&__IPSBAR[0x00027C]))
#define MCF_UART_UMR2 (*(vuint8 *)(void*)(&__IPSBAR[0x000280]))
#define MCF_UART_USR2 (*(vuint8 *)(void*)(&__IPSBAR[0x000284]))
#define MCF_UART_UCSR2 (*(vuint8 *)(void*)(&__IPSBAR[0x000284]))
#define MCF_UART_UCR2 (*(vuint8 *)(void*)(&__IPSBAR[0x000288]))
#define MCF_UART_URB2 (*(vuint8 *)(void*)(&__IPSBAR[0x00028C]))
#define MCF_UART_UTB2 (*(vuint8 *)(void*)(&__IPSBAR[0x00028C]))
#define MCF_UART_UIPCR2 (*(vuint8 *)(void*)(&__IPSBAR[0x000290]))
#define MCF_UART_UACR2 (*(vuint8 *)(void*)(&__IPSBAR[0x000290]))
#define MCF_UART_UISR2 (*(vuint8 *)(void*)(&__IPSBAR[0x000294]))
#define MCF_UART_UIMR2 (*(vuint8 *)(void*)(&__IPSBAR[0x000294]))
#define MCF_UART_UBG12 (*(vuint8 *)(void*)(&__IPSBAR[0x000298]))
#define MCF_UART_UBG22 (*(vuint8 *)(void*)(&__IPSBAR[0x00029C]))
#define MCF_UART_UIP2 (*(vuint8 *)(void*)(&__IPSBAR[0x0002B4]))
#define MCF_UART_UOP12 (*(vuint8 *)(void*)(&__IPSBAR[0x0002B8]))
#define MCF_UART_UOP02 (*(vuint8 *)(void*)(&__IPSBAR[0x0002BC]))
#define MCF_UART_UMR(x) (*(vuint8 *)(void*)(&__IPSBAR[0x000200+((x)*0x040)]))
#define MCF_UART_USR(x) (*(vuint8 *)(void*)(&__IPSBAR[0x000204+((x)*0x040)]))
#define MCF_UART_UCSR(x) (*(vuint8 *)(void*)(&__IPSBAR[0x000204+((x)*0x040)]))
#define MCF_UART_UCR(x) (*(vuint8 *)(void*)(&__IPSBAR[0x000208+((x)*0x040)]))
#define MCF_UART_URB(x) (*(vuint8 *)(void*)(&__IPSBAR[0x00020C+((x)*0x040)]))
#define MCF_UART_UTB(x) (*(vuint8 *)(void*)(&__IPSBAR[0x00020C+((x)*0x040)]))
#define MCF_UART_UIPCR(x) (*(vuint8 *)(void*)(&__IPSBAR[0x000210+((x)*0x040)]))
#define MCF_UART_UACR(x) (*(vuint8 *)(void*)(&__IPSBAR[0x000210+((x)*0x040)]))
#define MCF_UART_UISR(x) (*(vuint8 *)(void*)(&__IPSBAR[0x000214+((x)*0x040)]))
#define MCF_UART_UIMR(x) (*(vuint8 *)(void*)(&__IPSBAR[0x000214+((x)*0x040)]))
#define MCF_UART_UBG1(x) (*(vuint8 *)(void*)(&__IPSBAR[0x000218+((x)*0x040)]))
#define MCF_UART_UBG2(x) (*(vuint8 *)(void*)(&__IPSBAR[0x00021C+((x)*0x040)]))
#define MCF_UART_UIP(x) (*(vuint8 *)(void*)(&__IPSBAR[0x000234+((x)*0x040)]))
#define MCF_UART_UOP1(x) (*(vuint8 *)(void*)(&__IPSBAR[0x000238+((x)*0x040)]))
#define MCF_UART_UOP0(x) (*(vuint8 *)(void*)(&__IPSBAR[0x00023C+((x)*0x040)]))
/* Bit definitions and macros for MCF_UART_UMR */
#define MCF_UART_UMR_BC(x) (((x)&0x03)<<0)
#define MCF_UART_UMR_PT (0x04)
#define MCF_UART_UMR_PM(x) (((x)&0x03)<<3)
#define MCF_UART_UMR_ERR (0x20)
#define MCF_UART_UMR_RXIRQ (0x40)
#define MCF_UART_UMR_RXRTS (0x80)
#define MCF_UART_UMR_SB(x) (((x)&0x0F)<<0)
#define MCF_UART_UMR_TXCTS (0x10)
#define MCF_UART_UMR_TXRTS (0x20)
#define MCF_UART_UMR_CM(x) (((x)&0x03)<<6)
#define MCF_UART_UMR_PM_MULTI_ADDR (0x1C)
#define MCF_UART_UMR_PM_MULTI_DATA (0x18)
#define MCF_UART_UMR_PM_NONE (0x10)
#define MCF_UART_UMR_PM_FORCE_HI (0x0C)
#define MCF_UART_UMR_PM_FORCE_LO (0x08)
#define MCF_UART_UMR_PM_ODD (0x04)
#define MCF_UART_UMR_PM_EVEN (0x00)
#define MCF_UART_UMR_BC_5 (0x00)
#define MCF_UART_UMR_BC_6 (0x01)
#define MCF_UART_UMR_BC_7 (0x02)
#define MCF_UART_UMR_BC_8 (0x03)
#define MCF_UART_UMR_CM_NORMAL (0x00)
#define MCF_UART_UMR_CM_ECHO (0x40)
#define MCF_UART_UMR_CM_LOCAL_LOOP (0x80)
#define MCF_UART_UMR_CM_REMOTE_LOOP (0xC0)
#define MCF_UART_UMR_SB_STOP_BITS_1 (0x07)
#define MCF_UART_UMR_SB_STOP_BITS_15 (0x08)
#define MCF_UART_UMR_SB_STOP_BITS_2 (0x0F)
/* Bit definitions and macros for MCF_UART_USR */
#define MCF_UART_USR_RXRDY (0x01)
#define MCF_UART_USR_FFULL (0x02)
#define MCF_UART_USR_TXRDY (0x04)
#define MCF_UART_USR_TXEMP (0x08)
#define MCF_UART_USR_OE (0x10)
#define MCF_UART_USR_PE (0x20)
#define MCF_UART_USR_FE (0x40)
#define MCF_UART_USR_RB (0x80)
/* Bit definitions and macros for MCF_UART_UCSR */
#define MCF_UART_UCSR_TCS(x) (((x)&0x0F)<<0)
#define MCF_UART_UCSR_RCS(x) (((x)&0x0F)<<4)
#define MCF_UART_UCSR_RCS_SYS_CLK (0xD0)
#define MCF_UART_UCSR_RCS_CTM16 (0xE0)
#define MCF_UART_UCSR_RCS_CTM (0xF0)
#define MCF_UART_UCSR_TCS_SYS_CLK (0x0D)
#define MCF_UART_UCSR_TCS_CTM16 (0x0E)
#define MCF_UART_UCSR_TCS_CTM (0x0F)
/* Bit definitions and macros for MCF_UART_UCR */
#define MCF_UART_UCR_RXC(x) (((x)&0x03)<<0)
#define MCF_UART_UCR_TXC(x) (((x)&0x03)<<2)
#define MCF_UART_UCR_MISC(x) (((x)&0x07)<<4)
#define MCF_UART_UCR_NONE (0x00)
#define MCF_UART_UCR_STOP_BREAK (0x70)
#define MCF_UART_UCR_START_BREAK (0x60)
#define MCF_UART_UCR_BKCHGINT (0x50)
#define MCF_UART_UCR_RESET_ERROR (0x40)
#define MCF_UART_UCR_RESET_TX (0x30)
#define MCF_UART_UCR_RESET_RX (0x20)
#define MCF_UART_UCR_RESET_MR (0x10)
#define MCF_UART_UCR_TX_DISABLED (0x08)
#define MCF_UART_UCR_TX_ENABLED (0x04)
#define MCF_UART_UCR_RX_DISABLED (0x02)
#define MCF_UART_UCR_RX_ENABLED (0x01)
/* Bit definitions and macros for MCF_UART_UIPCR */
#define MCF_UART_UIPCR_CTS (0x01)
#define MCF_UART_UIPCR_COS (0x10)
/* Bit definitions and macros for MCF_UART_UACR */
#define MCF_UART_UACR_IEC (0x01)
/* Bit definitions and macros for MCF_UART_UISR */
#define MCF_UART_UISR_TXRDY (0x01)
#define MCF_UART_UISR_RXRDY_FU (0x02)
#define MCF_UART_UISR_DB (0x04)
#define MCF_UART_UISR_RXFTO (0x08)
#define MCF_UART_UISR_TXFIFO (0x10)
#define MCF_UART_UISR_RXFIFO (0x20)
#define MCF_UART_UISR_COS (0x80)
/* Bit definitions and macros for MCF_UART_UIMR */
#define MCF_UART_UIMR_TXRDY (0x01)
#define MCF_UART_UIMR_RXRDY_FU (0x02)
#define MCF_UART_UIMR_DB (0x04)
#define MCF_UART_UIMR_COS (0x80)
/* Bit definitions and macros for MCF_UART_UIP */
#define MCF_UART_UIP_CTS (0x01)
/* Bit definitions and macros for MCF_UART_UOP1 */
#define MCF_UART_UOP1_RTS (0x01)
/* Bit definitions and macros for MCF_UART_UOP0 */
#define MCF_UART_UOP0_RTS (0x01)
/********************************************************************/
#endif /* __MCF523X_UART_H__ */

View File

@@ -0,0 +1,86 @@
/*
* File: mcf523x_wtm.h
* Purpose: Register and bit definitions for the MCF523X
*
* Notes:
*
*/
#ifndef __MCF523X_WTM_H__
#define __MCF523X_WTM_H__
/*********************************************************************
*
* Watchdog Timer Modules (WTM)
*
*********************************************************************/
/* Register read/write macros */
#define MCF_WTM_WCR (*(vuint16*)(void*)(&__IPSBAR[0x140000]))
#define MCF_WTM_WMR (*(vuint16*)(void*)(&__IPSBAR[0x140002]))
#define MCF_WTM_WCNTR (*(vuint16*)(void*)(&__IPSBAR[0x140004]))
#define MCF_WTM_WSR (*(vuint16*)(void*)(&__IPSBAR[0x140006]))
/* Bit definitions and macros for MCF_WTM_WCR */
#define MCF_WTM_WCR_EN (0x0001)
#define MCF_WTM_WCR_HALTED (0x0002)
#define MCF_WTM_WCR_DOZE (0x0004)
#define MCF_WTM_WCR_WAIT (0x0008)
/* Bit definitions and macros for MCF_WTM_WMR */
#define MCF_WTM_WMR_WM0 (0x0001)
#define MCF_WTM_WMR_WM1 (0x0002)
#define MCF_WTM_WMR_WM2 (0x0004)
#define MCF_WTM_WMR_WM3 (0x0008)
#define MCF_WTM_WMR_WM4 (0x0010)
#define MCF_WTM_WMR_WM5 (0x0020)
#define MCF_WTM_WMR_WM6 (0x0040)
#define MCF_WTM_WMR_WM7 (0x0080)
#define MCF_WTM_WMR_WM8 (0x0100)
#define MCF_WTM_WMR_WM9 (0x0200)
#define MCF_WTM_WMR_WM10 (0x0400)
#define MCF_WTM_WMR_WM11 (0x0800)
#define MCF_WTM_WMR_WM12 (0x1000)
#define MCF_WTM_WMR_WM13 (0x2000)
#define MCF_WTM_WMR_WM14 (0x4000)
#define MCF_WTM_WMR_WM15 (0x8000)
/* Bit definitions and macros for MCF_WTM_WCNTR */
#define MCF_WTM_WCNTR_WC0 (0x0001)
#define MCF_WTM_WCNTR_WC1 (0x0002)
#define MCF_WTM_WCNTR_WC2 (0x0004)
#define MCF_WTM_WCNTR_WC3 (0x0008)
#define MCF_WTM_WCNTR_WC4 (0x0010)
#define MCF_WTM_WCNTR_WC5 (0x0020)
#define MCF_WTM_WCNTR_WC6 (0x0040)
#define MCF_WTM_WCNTR_WC7 (0x0080)
#define MCF_WTM_WCNTR_WC8 (0x0100)
#define MCF_WTM_WCNTR_WC9 (0x0200)
#define MCF_WTM_WCNTR_WC10 (0x0400)
#define MCF_WTM_WCNTR_WC11 (0x0800)
#define MCF_WTM_WCNTR_WC12 (0x1000)
#define MCF_WTM_WCNTR_WC13 (0x2000)
#define MCF_WTM_WCNTR_WC14 (0x4000)
#define MCF_WTM_WCNTR_WC15 (0x8000)
/* Bit definitions and macros for MCF_WTM_WSR */
#define MCF_WTM_WSR_WS0 (0x0001)
#define MCF_WTM_WSR_WS1 (0x0002)
#define MCF_WTM_WSR_WS2 (0x0004)
#define MCF_WTM_WSR_WS3 (0x0008)
#define MCF_WTM_WSR_WS4 (0x0010)
#define MCF_WTM_WSR_WS5 (0x0020)
#define MCF_WTM_WSR_WS6 (0x0040)
#define MCF_WTM_WSR_WS7 (0x0080)
#define MCF_WTM_WSR_WS8 (0x0100)
#define MCF_WTM_WSR_WS9 (0x0200)
#define MCF_WTM_WSR_WS10 (0x0400)
#define MCF_WTM_WSR_WS11 (0x0800)
#define MCF_WTM_WSR_WS12 (0x1000)
#define MCF_WTM_WSR_WS13 (0x2000)
#define MCF_WTM_WSR_WS14 (0x4000)
#define MCF_WTM_WSR_WS15 (0x8000)
/********************************************************************/
#endif /* __MCF523X_WTM_H__ */

View File

@@ -0,0 +1,190 @@
/*
* File: mcf5xxx.h
* Purpose: Definitions common to all ColdFire processors
*
* Notes:
*/
#ifndef _CPU_MCF5XXX_H
#define _CPU_MCF5XXX_H
/***********************************************************************/
/*
* Misc. Defines
*/
#ifdef FALSE
#undef FALSE
#endif
#define FALSE (0)
#ifdef TRUE
#undef TRUE
#endif
#define TRUE (1)
#ifdef NULL
#undef NULL
#endif
#define NULL (0)
/***********************************************************************/
/*
* The basic data types
*/
typedef unsigned char uint8; /* 8 bits */
typedef unsigned short int uint16; /* 16 bits */
typedef unsigned long int uint32; /* 32 bits */
typedef signed char int8; /* 8 bits */
typedef signed short int int16; /* 16 bits */
typedef signed long int int32; /* 32 bits */
typedef volatile uint8 vuint8; /* 8 bits */
typedef volatile uint16 vuint16; /* 16 bits */
typedef volatile uint32 vuint32; /* 32 bits */
/***********************************************************************/
/*
* Common M68K & ColdFire definitions
*/
#define ADDRESS uint32
#define INSTRUCTION uint16
#define ILLEGAL 0x4AFC
#define CPU_WORD_SIZE 16
#define MCF5XXX_SR_T (0x8000)
#define MCF5XXX_SR_S (0x2000)
#define MCF5XXX_SR_M (0x1000)
#define MCF5XXX_SR_IPL (0x0700)
#define MCF5XXX_SR_IPL_0 (0x0000)
#define MCF5XXX_SR_IPL_1 (0x0100)
#define MCF5XXX_SR_IPL_2 (0x0200)
#define MCF5XXX_SR_IPL_3 (0x0300)
#define MCF5XXX_SR_IPL_4 (0x0400)
#define MCF5XXX_SR_IPL_5 (0x0500)
#define MCF5XXX_SR_IPL_6 (0x0600)
#define MCF5XXX_SR_IPL_7 (0x0700)
#define MCF5XXX_SR_X (0x0010)
#define MCF5XXX_SR_N (0x0008)
#define MCF5XXX_SR_Z (0x0004)
#define MCF5XXX_SR_V (0x0002)
#define MCF5XXX_SR_C (0x0001)
#define MCF5XXX_CACR_CENB (0x80000000)
#define MCF5XXX_CACR_CPDI (0x10000000)
#define MCF5XXX_CACR_CPD (0x10000000)
#define MCF5XXX_CACR_CFRZ (0x08000000)
#define MCF5XXX_CACR_CINV (0x01000000)
#define MCF5XXX_CACR_DIDI (0x00800000)
#define MCF5XXX_CACR_DISD (0x00400000)
#define MCF5XXX_CACR_INVI (0x00200000)
#define MCF5XXX_CACR_INVD (0x00100000)
#define MCF5XXX_CACR_CEIB (0x00000400)
#define MCF5XXX_CACR_DCM_WR (0x00000000)
#define MCF5XXX_CACR_DCM_CB (0x00000100)
#define MCF5XXX_CACR_DCM_IP (0x00000200)
#define MCF5XXX_CACR_DCM (0x00000200)
#define MCF5XXX_CACR_DCM_II (0x00000300)
#define MCF5XXX_CACR_DBWE (0x00000100)
#define MCF5XXX_CACR_DWP (0x00000020)
#define MCF5XXX_CACR_EUST (0x00000010)
#define MCF5XXX_CACR_CLNF_00 (0x00000000)
#define MCF5XXX_CACR_CLNF_01 (0x00000002)
#define MCF5XXX_CACR_CLNF_10 (0x00000004)
#define MCF5XXX_CACR_CLNF_11 (0x00000006)
#define MCF5XXX_ACR_AB(a) ((a)&0xFF000000)
#define MCF5XXX_ACR_AM(a) (((a)&0xFF000000) >> 8)
#define MCF5XXX_ACR_EN (0x00008000)
#define MCF5XXX_ACR_SM_USER (0x00000000)
#define MCF5XXX_ACR_SM_SUPER (0x00002000)
#define MCF5XXX_ACR_SM_IGNORE (0x00006000)
#define MCF5XXX_ACR_ENIB (0x00000080)
#define MCF5XXX_ACR_CM (0x00000040)
#define MCF5XXX_ACR_DCM_WR (0x00000000)
#define MCF5XXX_ACR_DCM_CB (0x00000020)
#define MCF5XXX_ACR_DCM_IP (0x00000040)
#define MCF5XXX_ACR_DCM_II (0x00000060)
#define MCF5XXX_ACR_CM (0x00000040)
#define MCF5XXX_ACR_BWE (0x00000020)
#define MCF5XXX_ACR_WP (0x00000004)
#define MCF5XXX_RAMBAR_BA(a) ((a)&0xFFFFC000)
#define MCF5XXX_RAMBAR_PRI_00 (0x00000000)
#define MCF5XXX_RAMBAR_PRI_01 (0x00004000)
#define MCF5XXX_RAMBAR_PRI_10 (0x00008000)
#define MCF5XXX_RAMBAR_PRI_11 (0x0000C000)
#define MCF5XXX_RAMBAR_WP (0x00000100)
#define MCF5XXX_RAMBAR_CI (0x00000020)
#define MCF5XXX_RAMBAR_SC (0x00000010)
#define MCF5XXX_RAMBAR_SD (0x00000008)
#define MCF5XXX_RAMBAR_UC (0x00000004)
#define MCF5XXX_RAMBAR_UD (0x00000002)
#define MCF5XXX_RAMBAR_V (0x00000001)
/***********************************************************************/
/*
* The ColdFire family of processors has a simplified exception stack
* frame that looks like the following:
*
* 3322222222221111 111111
* 1098765432109876 5432109876543210
* 8 +----------------+----------------+
* | Program Counter |
* 4 +----------------+----------------+
* |FS/Fmt/Vector/FS| SR |
* SP --> 0 +----------------+----------------+
*
* The stack self-aligns to a 4-byte boundary at an exception, with
* the FS/Fmt/Vector/FS field indicating the size of the adjustment
* (SP += 0,1,2,3 bytes).
*/
#define MCF5XXX_RD_SF_FORMAT(PTR) \
((*((uint16 *)(PTR)) >> 12) & 0x00FF)
#define MCF5XXX_RD_SF_VECTOR(PTR) \
((*((uint16 *)(PTR)) >> 2) & 0x00FF)
#define MCF5XXX_RD_SF_FS(PTR) \
( ((*((uint16 *)(PTR)) & 0x0C00) >> 8) | (*((uint16 *)(PTR)) & 0x0003) )
#define MCF5XXX_SF_SR(PTR) *((uint16 *)(PTR)+1)
#define MCF5XXX_SF_PC(PTR) *((uint32 *)(PTR)+1)
/********************************************************************/
/*
* Functions provided by mcf5xxx.s
*/
int asm_set_ipl (uint32);
void mcf5xxx_wr_cacr (uint32);
void mcf5xxx_wr_acr0 (uint32);
void mcf5xxx_wr_acr1 (uint32);
void mcf5xxx_wr_acr2 (uint32);
void mcf5xxx_wr_acr3 (uint32);
void mcf5xxx_wr_other_a7 (uint32);
void mcf5xxx_wr_other_sp (uint32);
void mcf5xxx_wr_vbr (uint32);
void mcf5xxx_wr_macsr (uint32);
void mcf5xxx_wr_mask (uint32);
void mcf5xxx_wr_acc0 (uint32);
void mcf5xxx_wr_accext01 (uint32);
void mcf5xxx_wr_accext23 (uint32);
void mcf5xxx_wr_acc1 (uint32);
void mcf5xxx_wr_acc2 (uint32);
void mcf5xxx_wr_acc3 (uint32);
void mcf5xxx_wr_sr (uint32);
void mcf5xxx_wr_rambar0 (uint32);
void mcf5xxx_wr_rambar1 (uint32);
void mcf5xxx_wr_mbar (uint32);
void mcf5xxx_wr_mbar0 (uint32);
void mcf5xxx_wr_mbar1 (uint32);
/********************************************************************/
#endif /* _CPU_MCF5XXX_H */

View File

@@ -0,0 +1,596 @@
FUTURE
* TODO: The lwIP source code makes some invalid assumptions on processor
word-length, storage sizes and alignment. See the mailing lists for
problems with exoteric (/DSP) architectures showing these problems.
We still have to fix some of these issues neatly.
* TODO: the ARP layer is not protected against concurrent access. If
you run from a multitasking OS, serialize access to ARP (called from
your network device driver and from a timeout thread.)
* TODO: the PPP code is broken in a few ways. There are namespace
collisions on BSD systems and many assumptions on word-length
(sizeof(int)). In ppp.c an assumption is made on the availability of
a thread subsystem. Either PPP needs to be moved to contrib/ports/???
or rearranged to be more generic.
HISTORY
(CVS HEAD)
* [New changes go here]
(STABLE-1_1_1)
2006-03-03 Christiaan Simons
* ipv4/ip_frag.c: Added bound-checking assertions on ip_reassbitmap
access and added pbuf_alloc() return value checks.
2006-01-01 Leon Woestenberg <leon.woestenberg@gmx.net>
* tcp_{in,out}.c, tcp_out.c: Removed 'even sndbuf' fix in TCP, which is
now handled by the checksum routine properly.
2006-02-27 Leon Woestenberg <leon.woestenberg@gmx.net>
* pbuf.c: Fix alignment; pbuf_init() would not work unless
pbuf_pool_memory[] was properly aligned. (Patch by Curt McDowell.)
2005-12-20 Leon Woestenberg <leon.woestenberg@gmx.net>
* tcp.c: Remove PCBs which stay in LAST_ACK state too long. Patch
submitted by Mitrani Hiroshi.
2005-12-15 Christiaan Simons
* inet.c: Disabled the added summing routine to preserve code space.
2005-12-14 Leon Woestenberg <leon.woestenberg@gmx.net>
* tcp_in.c: Duplicate FIN ACK race condition fix by Kelvin Lawson.
Added Curt McDowell's optimized checksumming routine for future
inclusion. Need to create test case for unaliged, aligned, odd,
even length combination of cases on various endianess machines.
2005-12-09 Christiaan Simons
* inet.c: Rewrote standard checksum routine in proper portable C.
2005-11-25 Christiaan Simons
* udp.c tcp.c: Removed SO_REUSE hack. Should reside in socket code only.
* *.c: introduced cc.h LWIP_DEBUG formatters matching the u16_t, s16_t,
u32_t, s32_t typedefs. This solves most debug word-length assumes.
2005-07-17 Leon Woestenberg <leon.woestenberg@gmx.net>
* inet.c: Fixed unaligned 16-bit access in the standard checksum
routine by Peter Jolasson.
* slipif.c: Fixed implementation assumption of single-pbuf datagrams.
2005-02-04 Leon Woestenberg <leon.woestenberg@gmx.net>
* tcp_out.c: Fixed uninitialized 'queue' referenced in memerr branch.
* tcp_{out|in}.c: Applied patch fixing unaligned access.
2005-01-04 Leon Woestenberg <leon.woestenberg@gmx.net>
* pbuf.c: Fixed missing semicolon after LWIP_DEBUG statement.
2005-01-03 Leon Woestenberg <leon.woestenberg@gmx.net>
* udp.c: UDP pcb->recv() was called even when it was NULL.
(STABLE-1_1_0)
2004-12-28 Leon Woestenberg <leon.woestenberg@gmx.net>
* etharp.*: Disabled multiple packets on the ARP queue.
This clashes with TCP queueing.
2004-11-28 Leon Woestenberg <leon.woestenberg@gmx.net>
* etharp.*: Fixed race condition from ARP request to ARP timeout.
Halved the ARP period, doubled the period counts.
ETHARP_MAX_PENDING now should be at least 2. This prevents
the counter from reaching 0 right away (which would allow
too little time for ARP responses to be received).
2004-11-25 Leon Woestenberg <leon.woestenberg@gmx.net>
* dhcp.c: Decline messages were not multicast but unicast.
* etharp.c: ETHARP_CREATE is renamed to ETHARP_TRY_HARD.
Do not try hard to insert arbitrary packet's source address,
etharp_ip_input() now calls etharp_update() without ETHARP_TRY_HARD.
etharp_query() now always DOES call ETHARP_TRY_HARD so that users
querying an address will see it appear in the cache (DHCP could
suffer from this when a server invalidly gave an in-use address.)
* ipv4/ip_addr.h: Renamed ip_addr_maskcmp() to _netcmp() as we are
comparing network addresses (identifiers), not the network masks
themselves.
* ipv4/ip_addr.c: ip_addr_isbroadcast() now checks that the given
IP address actually belongs to the network of the given interface.
2004-11-24 Kieran Mansley <kjm25@cam.ac.uk>
* tcp.c: Increment pcb->snd_buf when ACK is received in SYN_SENT state.
(STABLE-1_1_0-RC1)
2004-10-16 Kieran Mansley <kjm25@cam.ac.uk>
* tcp.c: Add code to tcp_recved() to send an ACK (window update) immediately,
even if one is already pending, if the rcv_wnd is above a threshold
(currently TCP_WND/2). This avoids waiting for a timer to expire to send a
delayed ACK in order to open the window if the stack is only receiving data.
2004-09-12 Kieran Mansley <kjm25@cam.ac.uk>
* tcp*.*: Retransmit time-out handling improvement by Sam Jansen.
2004-08-20 Tony Mountifield <tony@softins.co.uk>
* etharp.c: Make sure the first pbuf queued on an ARP entry
is properly ref counted.
2004-07-27 Tony Mountifield <tony@softins.co.uk>
* debug.h: Added (int) cast in LWIP_DEBUGF() to avoid compiler
warnings about comparison.
* pbuf.c: Stopped compiler complaining of empty if statement
when LWIP_DEBUGF() empty. Closed an unclosed comment.
* tcp.c: Stopped compiler complaining of empty if statement
when LWIP_DEBUGF() empty.
* ip.h Corrected IPH_TOS() macro: returns a byte, so doesn't need htons().
* inet.c: Added a couple of casts to quiet the compiler.
No need to test isascii(c) before isdigit(c) or isxdigit(c).
2004-07-22 Tony Mountifield <tony@softins.co.uk>
* inet.c: Made data types consistent in inet_ntoa().
Added casts for return values of checksum routines, to pacify compiler.
* ip_frag.c, tcp_out.c, sockets.c, pbuf.c
Small corrections to some debugging statements, to pacify compiler.
2004-07-21 Tony Mountifield <tony@softins.co.uk>
* etharp.c: Removed spurious semicolon and added missing end-of-comment.
* ethernetif.c Updated low_level_output() to match prototype for
netif->linkoutput and changed low_level_input() similarly for consistency.
* api_msg.c: Changed recv_raw() from int to u8_t, to match prototype
of raw_recv() in raw.h and so avoid compiler error.
* sockets.c: Added trivial (int) cast to keep compiler happier.
* ip.c, netif.c Changed debug statements to use the tidier ip4_addrN() macros.
(STABLE-1_0_0)
++ Changes:
2004-07-05 Leon Woestenberg <leon.woestenberg@gmx.net>
* sockets.*: Restructured LWIP_PRIVATE_TIMEVAL. Make sure
your cc.h file defines this either 1 or 0. If non-defined,
defaults to 1.
* .c: Added <string.h> and <errno.h> includes where used.
* etharp.c: Made some array indices unsigned.
2004-06-27 Leon Woestenberg <leon.woestenberg@gmx.net>
* netif.*: Added netif_set_up()/down().
* dhcp.c: Changes to restart program flow.
2004-05-07 Leon Woestenberg <leon.woestenberg@gmx.net>
* etharp.c: In find_entry(), instead of a list traversal per candidate, do a
single-pass lookup for different candidates. Should exploit locality.
2004-04-29 Leon Woestenberg <leon.woestenberg@gmx.net>
* tcp*.c: Cleaned up source comment documentation for Doxygen processing.
* opt.h: ETHARP_ALWAYS_INSERT option removed to comply with ARP RFC.
* etharp.c: update_arp_entry() only adds new ARP entries when adviced to by
the caller. This deprecates the ETHARP_ALWAYS_INSERT overrule option.
++ Bug fixes:
2004-04-27 Leon Woestenberg <leon.woestenberg@gmx.net>
* etharp.c: Applied patch of bug #8708 by Toni Mountifield with a solution
suggested by Timmy Brolin. Fix for 32-bit processors that cannot access
non-aligned 32-bit words, such as soms 32-bit TCP/IP header fields. Fix
is to prefix the 14-bit Ethernet headers with two padding bytes.
2004-04-23 Leon Woestenberg <leon.woestenberg@gmx.net>
* ip_addr.c: Fix in the ip_addr_isbroadcast() check.
* etharp.c: Fixed the case where the packet that initiates the ARP request
is not queued, and gets lost. Fixed the case where the packets destination
address is already known; we now always queue the packet and perform an ARP
request.
(STABLE-0_7_0)
++ Bug fixes:
* Fixed TCP bug for SYN_SENT to ESTABLISHED state transition.
* Fixed TCP bug in dequeueing of FIN from out of order segment queue.
* Fixed two possible NULL references in rare cases.
(STABLE-0_6_6)
++ Bug fixes:
* Fixed DHCP which did not include the IP address in DECLINE messages.
++ Changes:
* etharp.c has been hauled over a bit.
(STABLE-0_6_5)
++ Bug fixes:
* Fixed TCP bug induced by bad window resizing with unidirectional TCP traffic.
* Packets sent from ARP queue had invalid source hardware address.
++ Changes:
* Pass-by ARP requests do now update the cache.
++ New features:
* No longer dependent on ctype.h.
* New socket options.
* Raw IP pcb support.
(STABLE-0_6_4)
++ Bug fixes:
* Some debug formatters and casts fixed.
* Numereous fixes in PPP.
++ Changes:
* DEBUGF now is LWIP_DEBUGF
* pbuf_dechain() has been re-enabled.
* Mentioned the changed use of CVS branches in README.
(STABLE-0_6_3)
++ Bug fixes:
* Fixed pool pbuf memory leak in pbuf_alloc().
Occured if not enough PBUF_POOL pbufs for a packet pbuf chain.
Reported by Savin Zlobec.
* PBUF_POOL chains had their tot_len field not set for non-first
pbufs. Fixed in pbuf_alloc().
++ New features:
* Added PPP stack contributed by Marc Boucher
++ Changes:
* Now drops short packets for ICMP/UDP/TCP protocols. More robust.
* ARP queueuing now queues the latest packet instead of the first.
This is the RFC recommended behaviour, but can be overridden in
lwipopts.h.
(0.6.2)
++ Bugfixes:
* TCP has been fixed to deal with the new use of the pbuf->ref
counter.
* DHCP dhcp_inform() crash bug fixed.
++ Changes:
* Removed pbuf_pool_free_cache and pbuf_pool_alloc_cache. Also removed
pbuf_refresh(). This has sped up pbuf pool operations considerably.
Implemented by David Haas.
(0.6.1)
++ New features:
* The packet buffer implementation has been enhanced to support
zero-copy and copy-on-demand for packet buffers which have their
payloads in application-managed memory.
Implemented by David Haas.
Use PBUF_REF to make a pbuf refer to RAM. lwIP will use zero-copy
if an outgoing packet can be directly sent on the link, or perform
a copy-on-demand when necessary.
The application can safely assume the packet is sent, and the RAM
is available to the application directly after calling udp_send()
or similar function.
++ Bugfixes:
* ARP_QUEUEING should now correctly work for all cases, including
PBUF_REF.
Implemented by Leon Woestenberg.
++ Changes:
* IP_ADDR_ANY is no longer a NULL pointer. Instead, it is a pointer
to a '0.0.0.0' IP address.
* The packet buffer implementation is changed. The pbuf->ref counter
meaning has changed, and several pbuf functions have been
adapted accordingly.
* netif drivers have to be changed to set the hardware address length field
that must be initialized correctly by the driver (hint: 6 for Ethernet MAC).
See the contrib/ports/c16x cs8900 driver as a driver example.
* netif's have a dhcp field that must be initialized to NULL by the driver.
See the contrib/ports/c16x cs8900 driver as a driver example.
(0.5.x) This file has been unmaintained up to 0.6.1. All changes are
logged in CVS but have not been explained here.
(0.5.3) Changes since version 0.5.2
++ Bugfixes:
* memp_malloc(MEMP_API_MSG) could fail with multiple application
threads because it wasn't protected by semaphores.
++ Other changes:
* struct ip_addr now packed.
* The name of the time variable in arp.c has been changed to ctime
to avoid conflicts with the time() function.
(0.5.2) Changes since version 0.5.1
++ New features:
* A new TCP function, tcp_tmr(), now handles both TCP timers.
++ Bugfixes:
* A bug in tcp_parseopt() could cause the stack to hang because of a
malformed TCP option.
* The address of new connections in the accept() function in the BSD
socket library was not handled correctly.
* pbuf_dechain() did not update the ->tot_len field of the tail.
* Aborted TCP connections were not handled correctly in all
situations.
++ Other changes:
* All protocol header structs are now packed.
* The ->len field in the tcp_seg structure now counts the actual
amount of data, and does not add one for SYN and FIN segments.
(0.5.1) Changes since version 0.5.0
++ New features:
* Possible to run as a user process under Linux.
* Preliminary support for cross platform packed structs.
* ARP timer now implemented.
++ Bugfixes:
* TCP output queue length was badly initialized when opening
connections.
* TCP delayed ACKs were not sent correctly.
* Explicit initialization of BSS segment variables.
* read() in BSD socket library could drop data.
* Problems with memory alignment.
* Situations when all TCP buffers were used could lead to
starvation.
* TCP MSS option wasn't parsed correctly.
* Problems with UDP checksum calculation.
* IP multicast address tests had endianess problems.
* ARP requests had wrong destination hardware address.
++ Other changes:
* struct eth_addr changed from u16_t[3] array to u8_t[6].
* A ->linkoutput() member was added to struct netif.
* TCP and UDP ->dest_* struct members where changed to ->remote_*.
* ntoh* macros are now null definitions for big endian CPUs.
(0.5.0) Changes since version 0.4.2
++ New features:
* Redesigned operating system emulation layer to make porting easier.
* Better control over TCP output buffers.
* Documenation added.
++ Bugfixes:
* Locking issues in buffer management.
* Bugfixes in the sequential API.
* IP forwarding could cause memory leakage. This has been fixed.
++ Other changes:
* Directory structure somewhat changed; the core/ tree has been
collapsed.
(0.4.2) Changes since version 0.4.1
++ New features:
* Experimental ARP implementation added.
* Skeleton Ethernet driver added.
* Experimental BSD socket API library added.
++ Bugfixes:
* In very intense situations, memory leakage could occur. This has
been fixed.
++ Other changes:
* Variables named "data" and "code" have been renamed in order to
avoid name conflicts in certain compilers.
* Variable++ have in appliciable cases been translated to ++variable
since some compilers generate better code in the latter case.
(0.4.1) Changes since version 0.4
++ New features:
* TCP: Connection attempts time out earlier than data
transmissions. Nagle algorithm implemented. Push flag set on the
last segment in a burst.
* UDP: experimental support for UDP-Lite extensions.
++ Bugfixes:
* TCP: out of order segments were in some cases handled incorrectly,
and this has now been fixed. Delayed acknowledgements was broken
in 0.4, has now been fixed. Binding to an address that is in use
now results in an error. Reset connections sometimes hung an
application; this has been fixed.
* Checksum calculation sometimes failed for chained pbufs with odd
lengths. This has been fixed.
* API: a lot of bug fixes in the API. The UDP API has been improved
and tested. Error reporting and handling has been
improved. Logical flaws and race conditions for incoming TCP
connections has been found and removed.
* Memory manager: alignment issues. Reallocating memory sometimes
failed, this has been fixed.
* Generic library: bcopy was flawed and has been fixed.
++ Other changes:
* API: all datatypes has been changed from generic ones such as
ints, to specified ones such as u16_t. Functions that return
errors now have the correct type (err_t).
* General: A lot of code cleaned up and debugging code removed. Many
portability issues have been fixed.
* The license was changed; the advertising clause was removed.
* C64 port added.
* Thanks: Huge thanks go to Dagan Galarneau, Horst Garnetzke, Petri
Kosunen, Mikael Caleres, and Frits Wilmink for reporting and
fixing bugs!
(0.4) Changes since version 0.3.1
* Memory management has been radically changed; instead of
allocating memory from a shared heap, memory for objects that are
rapidly allocated and deallocated is now kept in pools. Allocation
and deallocation from those memory pools is very fast. The shared
heap is still present but is used less frequently.
* The memory, memory pool, and packet buffer subsystems now support
4-, 2-, or 1-byte alignment.
* "Out of memory" situations are handled in a more robust way.
* Stack usage has been reduced.
* Easier configuration of lwIP parameters such as memory usage,
TTLs, statistics gathering, etc. All configuration parameters are
now kept in a single header file "lwipopts.h".
* The directory structure has been changed slightly so that all
architecture specific files are kept under the src/arch
hierarchy.
* Error propagation has been improved, both in the protocol modules
and in the API.
* The code for the RTXC architecture has been implemented, tested
and put to use.
* Bugs have been found and corrected in the TCP, UDP, IP, API, and
the Internet checksum modules.
* Bugs related to porting between a 32-bit and a 16-bit architecture
have been found and corrected.
* The license has been changed slightly to conform more with the
original BSD license, including the advertisement clause.
(0.3.1) Changes since version 0.3
* Fix of a fatal bug in the buffer management. Pbufs with allocated
RAM never returned the RAM when the pbuf was deallocated.
* TCP congestion control, window updates and retransmissions did not
work correctly. This has now been fixed.
* Bugfixes in the API.
(0.3) Changes since version 0.2
* New and improved directory structure. All include files are now
kept in a dedicated include/ directory.
* The API now has proper error handling. A new function,
netconn_err(), now returns an error code for the connection in
case of errors.
* Improvements in the memory management subsystem. The system now
keeps a pointer to the lowest free memory block. A new function,
mem_malloc2() tries to allocate memory once, and if it fails tries
to free some memory and retry the allocation.
* Much testing has been done with limited memory
configurations. lwIP now does a better job when overloaded.
* Some bugfixes and improvements to the buffer (pbuf) subsystem.
* Many bugfixes in the TCP code:
- Fixed a bug in tcp_close().
- The TCP receive window was incorrectly closed when out of
sequence segments was received. This has been fixed.
- Connections are now timed-out of the FIN-WAIT-2 state.
- The initial congestion window could in some cases be too
large. This has been fixed.
- The retransmission queue could in some cases be screwed up. This
has been fixed.
- TCP RST flag now handled correctly.
- Out of sequence data was in some cases never delivered to the
application. This has been fixed.
- Retransmitted segments now contain the correct acknowledgment
number and advertised window.
- TCP retransmission timeout backoffs are not correctly computed
(ala BSD). After a number of retransmissions, TCP now gives up
the connection.
* TCP connections now are kept on three lists, one for active
connections, one for listening connections, and one for
connections that are in TIME-WAIT. This greatly speeds up the fast
timeout processing for sending delayed ACKs.
* TCP now provides proper feedback to the application when a
connection has been successfully set up.
* More comments have been added to the code. The code has also been
somewhat cleaned up.
(0.2) Initial public release.

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/

View File

@@ -0,0 +1,4 @@
src/ - The source code for the lwIP TCP/IP stack.
doc/ - The documentation for lwIP.
See also the FILES file in each subdirectory.

View File

@@ -0,0 +1,74 @@
INTRODUCTION
lwIP is a small independent implementation of the TCP/IP protocol
suite that has been developed by Adam Dunkels at the Computer and
Networks Architectures (CNA) lab at the Swedish Institute of Computer
Science (SICS).
The focus of the lwIP TCP/IP implementation is to reduce the RAM usage
while still having a full scale TCP. This making lwIP suitable for use
in embedded systems with tens of kilobytes of free RAM and room for
around 40 kilobytes of code ROM.
FEATURES
* IP (Internet Protocol) including packet forwarding over multiple
network interfaces
* ICMP (Internet Control Message Protocol) for network maintenance
and debugging
* UDP (User Datagram Protocol) including experimental UDP-lite
extensions
* TCP (Transmission Control Protocol) with congestion control, RTT
estimation and fast recovery/fast retransmit
* Specialized API for enhanced performance
* Optional Berkeley socket API
LICENSE
lwIP is freely available under a BSD license.
DEVELOPMENT
lwIP has grown into an excellent TCP/IP stack for embedded devices,
and developers using the stack often submit bug fixes, improvements,
and additions to the stack to further increase its usefulness.
Development of lwIP is hosted on Savannah, a central point for
software development, maintenance and distribution. Everyone can
help improve lwIP by use of Savannah's interface, CVS and the
mailing list. A core team of developers will commit changes to the
CVS source tree.
The lwIP TCP/IP stack is maintained in the 'lwip' CVS module and
contributions (such as platform ports) are in the 'contrib' module.
See doc/savannah.txt for details on CVS server access for users and
developers.
Last night's CVS tar ball can be downloaded from:
http://savannah.gnu.org/cvs.backups/lwip.tar.gz [CHANGED - NEEDS FIXING]
The current CVS trees are web-browsable:
http://savannah.nongnu.org/cgi-bin/viewcvs/lwip/lwip/
http://savannah.nongnu.org/cgi-bin/viewcvs/lwip/contrib/
Submit patches and bugs via the lwIP project page:
http://savannah.nongnu.org/projects/lwip/
DOCUMENTATION
The original out-dated homepage of lwIP and Adam Dunkels' papers on
lwIP are at the official lwIP home page:
http://www.sics.se/~adam/lwip/
Self documentation of the source code is regularly extracted from the
current CVS sources and is available from this web page:
http://www.nongnu.org/lwip/
Reading Adam's papers, the files in docs/, browsing the source code
documentation and browsing the mailing list archives is a good way to
become familiar with the design of lwIP.
Adam Dunkels <adam@sics.se>
Leon Woestenberg <leon.woestenberg@gmx.net>

View File

@@ -0,0 +1,77 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
* Modifcations: Christian Walter <wolti@sil.at>
*/
#ifndef __CC_H__
#define __CC_H__
/* ------------------------ System includes ------------------------------- */
#include <string.h>
/* ------------------------ Project includes ------------------------------ */
#include "cpu.h"
#include "sys_arch.h"
/* ------------------------ Defines --------------------------------------- */
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_STRUCT __attribute__ ((__packed__))
#define PACK_STRUCT_END
#define PACK_STRUCT_FIELD( x ) x
#define ALIGN_STRUCT_8_BEGIN
#define ALIGN_STRUCT_8 __attribute__ ((aligned (8)))
#define ALIGN_STRUCT_8_END
#define LWIP_PLATFORM_ASSERT( x ) sys_assert( x )
#define LWIP_PLATFORM_DIAG( x, ... ) do{ sys_debug x; } while( 0 );
/* Define (sn)printf formatters for these lwIP types */
#define U16_F "hu"
#define S16_F "hd"
#define X16_F "hx"
#define U32_F "lu"
#define S32_F "ld"
#define X32_F "lx"
/* ------------------------ Type definitions ------------------------------ */
typedef unsigned char u8_t;
typedef signed char s8_t;
typedef unsigned short u16_t;
typedef signed short s16_t;
typedef unsigned long u32_t;
typedef signed long s32_t;
typedef u32_t mem_ptr_t;
typedef int sys_prot_t;
/* ------------------------ Prototypes ------------------------------------ */
#endif

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __CPU_H__
#define __CPU_H__
/* ------------------------ Defines --------------------------------------- */
#define BYTE_ORDER BIG_ENDIAN
#endif

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __PERF_H__
#define __PERF_H__
/* ------------------------ Defines --------------------------------------- */
#define PERF_START /* null definition */
#define PERF_STOP(x) /* null definition */
#endif

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __SYS_ARCH_H__
#define __SYS_ARCH_H__
/* ------------------------ Project includes ------------------------------ */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* ------------------------ Defines --------------------------------------- */
#define SYS_MBOX_NULL ( xQueueHandle )0
#define SYS_THREAD_NULL NULL
#define SYS_SEM_NULL ( xSemaphoreHandle )0
#define SIO_FD_NULL ( sio_fd_t )NULL
/* ------------------------ Type definitions ------------------------------ */
typedef xSemaphoreHandle sys_sem_t;
typedef xQueueHandle sys_mbox_t;
typedef xTaskHandle sys_thread_t;
/* ------------------------ Prototypes ------------------------------------ */
sys_thread_t sys_arch_thread_new( void ( *thread ) ( void *arg ), void *arg,
int prio, size_t ssize );
sys_thread_t sys_arch_thread_current( void );
void sys_arch_thread_remove( sys_thread_t hdl );
void sys_assert( const char *const msg );
void sys_debug( const char *const fmt, ... );
#endif

View File

@@ -0,0 +1,581 @@
/*
* Copyright (c) 2006 Christian Walter
* 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.
*
* Author: Christian Walter <wolti@sil.at>
*
* TODO:
* - Introduce another task create function in the sys_arch layer which allows
* for passing the stack size.
* - Avoid copying the buffers - this requires changeing the nbuf driver code
* to use the lwIP pbuf buffer implementation.
*
* File: $Id$
*/
/* ------------------------ System includes ------------------------------- */
#include <stdlib.h>
/* ------------------------ Platform includes ----------------------------- */
#include "mcf5xxx.h"
#include "mcf523x.h"
#include "nbuf.h"
/* ------------------------ lwIP includes --------------------------------- */
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include "lwip/stats.h"
#include "lwip/debug.h"
#include "netif/etharp.h"
/* ------------------------ Defines --------------------------------------- */
#ifdef FEC_DEBUG
#define FEC_DEBUG_INIT \
do \
{ \
MCF_GPIO_PDDR_FECI2C = ( MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C0 | \
MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C1 ); \
} while( 0 )
#define FEC_DEBUG_RX_TIMING( x ) \
do \
{ \
if( x ) \
MCF_GPIO_PPDSDR_FECI2C = MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C0; \
else \
MCF_GPIO_PCLRR_FECI2C = ~( MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C0 ); \
} while( 0 )
#define FEC_DEBUG_TX_TIMING( x ) \
do \
{ \
if( x ) \
MCF_GPIO_PPDSDR_FECI2C = MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C1; \
else \
MCF_GPIO_PCLRR_FECI2C = ~( MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C1 ); \
} while( 0 )
#else
#define FEC_DEBUG DBG_OFF
#define FEC_DEBUG_INIT
#define FEC_DEBUG_RX_TIMING( x )
#define FEC_DEBUG_TX_TIMING( x )
#endif
#define MCF_FEC_INT_LEVEL ( 6 )
#define MCF_FEC_INT_PRIORITY ( 0 )
#define MCF_FEC_VEC_RXF ( 64 + 27 )
#define MCF_FEC_MTU ( 1518 )
#define ETH_ADDR_LEN ( 6 )
#define TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
/* ------------------------ Type definitions ------------------------------ */
typedef struct
{
struct netif *netif; /* lwIP network interface. */
struct eth_addr *self; /* MAC address of FEC interface. */
sys_sem_t tx_sem; /* Control access to transmitter. */
sys_sem_t rx_sem; /* Semaphore to signal receive thread. */
} mcf523xfec_if_t;
/* ------------------------ Static variables ------------------------------ */
static mcf523xfec_if_t *fecif_g;
/* ------------------------ Static functions ------------------------------ */
static err_t mcf523xfec_output( struct netif *, struct pbuf *, struct ip_addr * );
static err_t mcf523xfec_output_raw( struct netif *, struct pbuf * );
static void mcf523xfec_reset( mcf523xfec_if_t * fecif );
static void mcf523xfec_enable( mcf523xfec_if_t * fecif );
static void mcf523xfec_disable( mcf523xfec_if_t * fecif );
static void mcf523xfec_get_mac( mcf523xfec_if_t * fecif, struct eth_addr *mac );
static void mcf523xfec_rx_irq( void );
static void mcf523xfec_rx_task( void *arg );
static void arp_timer( void *arg );
static void eth_input( struct netif *netif, struct pbuf *p );
/* ------------------------ Start implementation -------------------------- */
static void
arp_timer( void *arg )
{
( void )arg;
etharp_tmr( );
sys_timeout( ARP_TMR_INTERVAL, arp_timer, NULL );
}
err_t
mcf523xfec_output_raw( struct netif *netif, struct pbuf *p )
{
err_t res;
nbuf_t *pNBuf;
mcf523xfec_if_t *fecif = netif->state;
int i;
struct pbuf *q;
#if ETH_PAD_SIZE
pbuf_header( p, -ETH_PAD_SIZE ); /* drop the padding word */
#endif
/* Test if we can handle such big frames. If not drop it. */
if( p->tot_len > MCF_FEC_MTU )
{
#if LINK_STATS
lwip_stats.link.lenerr++;
#endif
res = ERR_BUF;
}
/* Test if our network buffer scheme can handle a packet of this size. If
* not drop it and return a memory error. */
else if( p->tot_len > TX_BUFFER_SIZE )
{
#ifdef LINK_STATS
lwip_stats.link.memerr++;
#endif
res = ERR_MEM;
}
/* Allocate a transmit buffer. If no buffer is available drop the frame. */
else if( ( pNBuf = nbuf_tx_allocate( ) ) == NULL )
{
LWIP_ASSERT( "mcf523xfec_output_raw: pNBuf != NULL\n", pNBuf != NULL );
#ifdef LINK_STATS
lwip_stats.link.memerr++;
#endif
res = ERR_MEM;
}
else
{
q = p;
i = 0;
do
{
memcpy( &pNBuf->data[i], q->payload, q->len );
i += q->len;
}
while( ( q = q->next ) != NULL );
pNBuf->length = p->tot_len;
/* Set Frame ready for transmission. */
pNBuf->status |= TX_BD_R;
/* Mark the buffer as not in use so the FEC can take it. */
nbuf_tx_release( pNBuf );
/* Indicate that a new transmit buffer has been produced. */
MCF_FEC_TDAR = 1;
#if LINK_STATS
lwip_stats.link.xmit++;
#endif
res = ERR_OK;
}
sys_sem_signal( fecif->tx_sem );
#if ETH_PAD_SIZE
buf_header( p, ETH_PAD_SIZE );
#endif
return res;
}
/* This function is called by the TCP/IP stack when an IP packet should be
* sent. It uses the ethernet ARP module provided by lwIP to resolve the
* destination MAC address. The ARP module will later call our low level
* output function mcf523xfec_output_raw.
*/
err_t
mcf523xfec_output( struct netif * netif, struct pbuf * p, struct ip_addr * ipaddr )
{
err_t res;
mcf523xfec_if_t *fecif = netif->state;
FEC_DEBUG_TX_TIMING( 1 );
/* Make sure only one thread is in this function. */
sys_sem_wait( fecif->tx_sem );
res = etharp_output( netif, ipaddr, p );
FEC_DEBUG_TX_TIMING( 0 );
return res;
}
void
mcf523xfec_rx_task( void *arg )
{
mcf523xfec_if_t *fecif = arg;
struct pbuf *p, *q;
nbuf_t *pNBuf;
uint8 *pPayLoad;
do
{
sys_sem_wait( fecif->rx_sem );
while( nbuf_rx_next_ready( ) )
{
pNBuf = nbuf_rx_allocate( );
if( pNBuf != NULL )
{
LWIP_ASSERT( "mcf523xfec_rx_task: pNBuf->status & RX_BD_L ",
pNBuf->status & RX_BD_L );
/* This flags indicate that the frame has been damaged. In
* this case we must update the link stats if enabled and
* remove the frame from the FEC. */
if( pNBuf->status & ( RX_BD_LG | RX_BD_NO | RX_BD_CR | RX_BD_OV ) )
{
#ifdef LINK_STATS
lwip_stats.link.drop++;
if( pNBuf->status & RX_BD_LG )
{
lwip_stats.link.lenerr++;
}
else if( pNBuf->status & ( RX_BD_NO | RX_BD_OV ) )
{
lwip_stats.link.err++;
}
else
{
lwip_stats.link.chkerr++;
}
#endif
}
else
{
/* The frame must no be valid. Perform some checks to see if the FEC
* driver is working correctly.
*/
LWIP_ASSERT( "mcf523xfec_rx_task: pNBuf->length != 0", pNBuf->length != 0 );
p = pbuf_alloc( PBUF_RAW, pNBuf->length, PBUF_POOL );
if( p != NULL )
{
#if ETH_PAD_SIZE
pbuf_header( p, -ETH_PAD_SIZE );
#endif
pPayLoad = pNBuf->data;
for( q = p; q != NULL; q = q->next )
{
memcpy( q->payload, pPayLoad, q->len );
pPayLoad += q->len;
}
#if ETH_PAD_SIZE
pbuf_header( p, ETH_PAD_SIZE );
#endif
/* Ethernet frame received. Handling it is not device
* dependent and therefore done in another function.
*/
eth_input( fecif->netif, p );
}
}
nbuf_rx_release( pNBuf );
/* Tell the HW that there are new free RX buffers. */
MCF_FEC_RDAR = 1;
}
else
{
#if LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.drop++;
#endif
}
}
/* Set RX Debug PIN to low since handling of next frame is possible. */
FEC_DEBUG_RX_TIMING( 0 );
}
while( 1 );
}
void
eth_input( struct netif *netif, struct pbuf *p )
{
struct eth_hdr *eth_hdr = p->payload;
LWIP_ASSERT( "eth_input: p != NULL ", p != NULL );
switch ( htons( eth_hdr->type ) )
{
case ETHTYPE_IP:
/* Pass to ARP layer. */
etharp_ip_input( netif, p );
/* Skip Ethernet header. */
pbuf_header( p, ( s16_t ) - sizeof( struct eth_hdr ) );
/* Pass to network layer. */
netif->input( p, netif );
break;
case ETHTYPE_ARP:
/* Pass to ARP layer. */
etharp_arp_input( netif, ( struct eth_addr * )netif->hwaddr, p );
break;
default:
pbuf_free( p );
break;
}
}
void
mcf523xfec_rx_irq( void )
{
static portBASE_TYPE xNeedSwitch = pdFALSE;
/* Workaround GCC if frame pointers are enabled. This is an ISR and
* we must not modify the stack before portENTER_SWITCHING_ISR( )
* has been called. */
#if _GCC_USES_FP == 1
asm volatile ( "unlk %fp\n\t" );
#endif
/* This ISR can cause a context switch, so the first statement must be
* a call to the portENTER_SWITCHING_ISR() macro.
*/
portENTER_SWITCHING_ISR( );
/* Set Debug PIN to high to measure RX latency. */
FEC_DEBUG_RX_TIMING( 1 );
/* Clear FEC RX Event from the Event Register (by writing 1) */
if( MCF_FEC_EIR & ( MCF_FEC_EIR_RXB | MCF_FEC_EIR_RXF ) )
{
/* Clear interrupt from EIR register immediately */
MCF_FEC_EIR = ( MCF_FEC_EIR_RXB | MCF_FEC_EIR_RXF );
xNeedSwitch = xSemaphoreGiveFromISR( fecif_g->rx_sem, pdFALSE );
}
portEXIT_SWITCHING_ISR( xNeedSwitch );
}
void
mcf523xfec_reset( mcf523xfec_if_t * fecif )
{
extern void ( *__RAMVEC[] ) ( );
int old_ipl = asm_set_ipl( 7 );
/* Reset the FEC - equivalent to a hard reset */
MCF_FEC_ECR = MCF_FEC_ECR_RESET;
/* Wait for the reset sequence to complete */
while( MCF_FEC_ECR & MCF_FEC_ECR_RESET );
/* Disable all FEC interrupts by clearing the EIMR register */
MCF_FEC_EIMR = 0;
/* Clear any interrupts by setting all bits in the EIR register */
MCF_FEC_EIR = 0xFFFFFFFFUL;
/* Configure Interrupt vectors. */
__RAMVEC[MCF_FEC_VEC_RXF] = mcf523xfec_rx_irq;
/* Set the source address for the controller */
MCF_FEC_PALR =
( fecif->self->addr[0] << 24U ) | ( fecif->self->addr[1] << 16U ) |
( fecif->self->addr[2] << 8U ) | ( fecif->self->addr[3] << 0U );
MCF_FEC_PAUR = ( fecif->self->addr[4] << 24U ) | ( fecif->self->addr[5] << 16U );
/* Initialize the hash table registers */
MCF_FEC_IAUR = 0;
MCF_FEC_IALR = 0;
/* Set Receive Buffer Size */
#if RX_BUFFER_SIZE != 2048
#error "RX_BUFFER_SIZE must be set to 2048 for safe FEC operation."
#endif
MCF_FEC_EMRBR = RX_BUFFER_SIZE - 1;
/* Point to the start of the circular Rx buffer descriptor queue */
MCF_FEC_ERDSR = nbuf_get_start( NBUF_RX );
/* Point to the start of the circular Tx buffer descriptor queue */
MCF_FEC_ETDSR = nbuf_get_start( NBUF_TX );
/* Set the tranceiver interface to MII mode */
MCF_FEC_RCR = MCF_FEC_RCR_MAX_FL( MCF_FEC_MTU ) | MCF_FEC_RCR_MII_MODE;
/* Set MII Speed Control Register for 2.5Mhz */
MCF_FEC_MSCR = MCF_FEC_MSCR_MII_SPEED( FSYS_2 / ( 2UL * 2500000UL ) );
/* Only operate in half-duplex, no heart beat control */
MCF_FEC_TCR = 0;
/* Enable Debug support */
FEC_DEBUG_INIT;
FEC_DEBUG_RX_TIMING( 0 );
FEC_DEBUG_TX_TIMING( 0 );
( void )asm_set_ipl( old_ipl );
}
void
mcf523xfec_get_mac( mcf523xfec_if_t * hw, struct eth_addr *mac )
{
int i;
static const struct eth_addr mac_default = {
{0x00, 0xCF, 0x52, 0x35, 0x00, 0x01}
};
( void )hw;
for( i = 0; i < ETH_ADDR_LEN; i++ )
{
mac->addr[i] = mac_default.addr[i];
}
}
void
mcf523xfec_enable( mcf523xfec_if_t * fecif )
{
( void )fecif;
int old_ipl = asm_set_ipl( 7 );
/* Configure I/O pins for the FEC. */
MCF_GPIO_PAR_FECI2C = ( MCF_GPIO_PAR_FECI2C_PAR_EMDC_FEC | MCF_GPIO_PAR_FECI2C_PAR_EMDIO_FEC );
/* Allow interrupts by setting IMR register */
MCF_FEC_EIMR = MCF_FEC_EIMR_RXF;
/* Configure the interrupt controller. */
MCF_INTC0_ICR27 = ( MCF_INTC0_ICRn_IL( MCF_FEC_INT_LEVEL ) |
MCF_INTC0_ICRn_IP( MCF_FEC_INT_PRIORITY ) );
MCF_INTC0_IMRL &= ~( MCF_INTC0_IMRL_INT_MASK27 | MCF_INTC0_IMRL_MASKALL );
/* Enable FEC */
MCF_FEC_ECR = MCF_FEC_ECR_ETHER_EN;
/* Indicate that there have been empty receive buffers produced */
MCF_FEC_RDAR = 1;
( void )asm_set_ipl( old_ipl );
}
void
mcf523xfec_disable( mcf523xfec_if_t * fecif )
{
( void )fecif;
int old_ipl = asm_set_ipl( 7 );
/* Set the Graceful Transmit Stop bit */
MCF_FEC_TCR = ( MCF_FEC_TCR | MCF_FEC_TCR_GTS );
/* Wait for the current transmission to complete */
while( !( MCF_FEC_EIR & MCF_FEC_EIR_GRA ) );
/* Clear the GRA event */
MCF_FEC_EIR = MCF_FEC_EIR_GRA;
/* Disable the FEC */
MCF_FEC_ECR = 0;
/* Disable all FEC interrupts by clearing the IMR register */
MCF_FEC_EIMR = 0;
/* Unconfigure the interrupt controller. */
MCF_INTC0_ICR27 = MCF_INTC0_ICRn_IL( 0 ) | MCF_INTC0_ICRn_IP( 0 );
MCF_INTC0_IMRL |= MCF_INTC0_IMRL_INT_MASK27;
/* Clear the GTS bit so frames can be tranmitted when restarted */
MCF_FEC_TCR = ( MCF_FEC_TCR & ~MCF_FEC_TCR_GTS );
/* Disable I/O pins used by the FEC. */
MCF_GPIO_PAR_FECI2C &= ~( MCF_GPIO_PAR_FECI2C_PAR_EMDC_FEC |
MCF_GPIO_PAR_FECI2C_PAR_EMDIO_FEC );
( void )asm_set_ipl( old_ipl );
}
err_t
mcf523xfec_init( struct netif *netif )
{
err_t res;
mcf523xfec_if_t *fecif = mem_malloc( sizeof( mcf523xfec_if_t ) );
if( fecif != NULL )
{
/* Global copy used in ISR. */
fecif_g = fecif;
fecif->self = ( struct eth_addr * )&netif->hwaddr[0];
fecif->netif = netif;
fecif->tx_sem = NULL;
fecif->rx_sem = NULL;
if( ( fecif->tx_sem = sys_sem_new( 1 ) ) == NULL )
{
res = ERR_MEM;
}
else if( ( fecif->rx_sem = sys_sem_new( 0 ) ) == NULL )
{
res = ERR_MEM;
}
else if( sys_thread_new( mcf523xfec_rx_task, fecif, TASK_PRIORITY ) == NULL )
{
res = ERR_MEM;
}
else
{
netif->state = fecif;
netif->name[0] = 'C';
netif->name[1] = 'F';
netif->hwaddr_len = ETH_ADDR_LEN;
netif->mtu = MCF_FEC_MTU;
netif->flags = NETIF_FLAG_BROADCAST;
netif->output = mcf523xfec_output;
netif->linkoutput = mcf523xfec_output_raw;
nbuf_init( );
mcf523xfec_get_mac( fecif, fecif->self );
mcf523xfec_reset( fecif );
mcf523xfec_enable( fecif );
etharp_init( );
sys_timeout( ARP_TMR_INTERVAL, arp_timer, NULL );
res = ERR_OK;
}
if( res != ERR_OK )
{
free( fecif );
if( fecif->tx_sem != NULL )
{
mem_free( fecif->tx_sem );
}
if( fecif->rx_sem != NULL )
{
mem_free( fecif->rx_sem );
}
}
}
else
{
res = ERR_MEM;
}
return res;
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2006 Christian Walter
* 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.
*
* Author: Christian Walter <wolti@sil.at>
*
* File: $Id$
*/
#ifndef _FEC_H
#define _FEC_H
/* ------------------------ Defines --------------------------------------- */
/* ------------------------ Prototypes ------------------------------------ */
err_t mcf523xfec_init( struct netif * netif );
#endif

View File

@@ -0,0 +1,212 @@
/*
* Copyright (c) 2006 Christian Walter
* 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.
*
* Note: Most of the network buffer code is based on the MCF5235 examples from
* Freescale.
*
* File: $Id$
*/
/* ------------------------ Platform includes ----------------------------- */
#include "mcf5xxx.h"
#include "mcf523x.h"
#include "nbuf.h"
/* ------------------------ Static variables ------------------------------ */
/* Buffer descriptor indexes */
static uint8 tx_bd_idx;
static uint8 rx_bd_idx;
/* Buffer Descriptors -- must be aligned on a 4-byte boundary but a
* 16-byte boundary is recommended. */
static nbuf_t tx_nbuf[sizeof( nbuf_t ) * NUM_TXBDS] ATTR_FECMEM;
static nbuf_t rx_nbuf[sizeof( nbuf_t ) * NUM_RXBDS] ATTR_FECMEM;
/* Data Buffers -- must be aligned on a 16-byte boundary. */
static uint8 tx_buf[TX_BUFFER_SIZE * NUM_TXBDS] ATTR_FECMEM;
static uint8 rx_buf[RX_BUFFER_SIZE * NUM_RXBDS] ATTR_FECMEM;
/* ------------------------ Start implementation -------------------------- */
void
nbuf_init( )
{
uint8 i;
/* Initialize receive descriptor ring */
for( i = 0; i < NUM_RXBDS; i++ )
{
rx_nbuf[i].status = RX_BD_E;
rx_nbuf[i].length = 0;
rx_nbuf[i].data = &rx_buf[i * RX_BUFFER_SIZE];
}
/* Set the Wrap bit on the last one in the ring */
rx_nbuf[NUM_RXBDS - 1].status |= RX_BD_W;
/* Initialize transmit descriptor ring */
for( i = 0; i < NUM_TXBDS; i++ )
{
tx_nbuf[i].status = TX_BD_L | TX_BD_TC;
tx_nbuf[i].length = 0;
tx_nbuf[i].data = &tx_buf[i * TX_BUFFER_SIZE];
}
/* Set the Wrap bit on the last one in the ring */
tx_nbuf[NUM_TXBDS - 1].status |= TX_BD_W;
/* Initialize the buffer descriptor indexes */
tx_bd_idx = rx_bd_idx = 0;
return;
}
/********************************************************************/
uint32
nbuf_get_start( uint8 direction )
{
/*
* Return the address of the first buffer descriptor in the ring.
* This routine is needed by the FEC of the MPC860T , MCF5282, and MCF523x
* in order to write the Rx/Tx descriptor ring start registers
*/
switch ( direction )
{
case NBUF_RX:
return ( uint32 ) rx_nbuf;
case NBUF_TX:
default:
return ( uint32 ) tx_nbuf;
}
}
/********************************************************************/
nbuf_t *
nbuf_rx_allocate( )
{
/* This routine alters shared data. Disable interrupts! */
int old_ipl = asm_set_ipl( 6 );
/* Return a pointer to the next empty Rx Buffer Descriptor */
int i = rx_bd_idx;
/* Check to see if the ring of BDs is full */
if( rx_nbuf[i].status & RX_BD_INUSE )
return NULL;
/* Mark the buffer as in use */
rx_nbuf[i].status |= RX_BD_INUSE;
/* increment the circular index */
rx_bd_idx = ( uint8 ) ( ( rx_bd_idx + 1 ) % NUM_RXBDS );
/* Restore previous IPL */
asm_set_ipl( old_ipl );
return &rx_nbuf[i];
}
/********************************************************************/
nbuf_t *
nbuf_tx_allocate( )
{
/* This routine alters shared data. Disable interrupts! */
int old_ipl = asm_set_ipl( 6 );
/* Return a pointer to the next empty Tx Buffer Descriptor */
int i = tx_bd_idx;
/* Check to see if ring of BDs is full */
if( ( tx_nbuf[i].status & TX_BD_INUSE ) || ( tx_nbuf[i].status & TX_BD_R ) )
return NULL;
/* Mark the buffer as Ready (in use) */
/* FEC must set R bit in transmit routine */
tx_nbuf[i].status |= TX_BD_INUSE;
/* increment the circular index */
tx_bd_idx = ( uint8 ) ( ( tx_bd_idx + 1 ) % NUM_TXBDS );
/* Restore previous IPL */
asm_set_ipl( old_ipl );
return &tx_nbuf[i];
}
/********************************************************************/
void
nbuf_rx_release( nbuf_t * pNbuf )
{
/* This routine alters shared data. Disable interrupts! */
int old_ipl = asm_set_ipl( 6 );
/* Mark the buffer as empty and not in use */
pNbuf->status |= RX_BD_E;
pNbuf->status &= ~RX_BD_INUSE;
/* Restore previous IPL */
asm_set_ipl( old_ipl );
}
/********************************************************************/
void
nbuf_tx_release( nbuf_t * pNbuf )
{
/* This routine alters shared data. Disable interrupts! */
int old_ipl = asm_set_ipl( 6 );
/* Mark the buffer as not in use */
pNbuf->status &= ~TX_BD_INUSE;
/* Restore previous IPL */
asm_set_ipl( old_ipl );
}
/********************************************************************/
int
nbuf_rx_next_ready( )
{
/****************************************************************
This function checks the EMPTY bit of the next Rx buffer to be
allocated. If the EMPTY bit is cleared, then the next buffer in
the ring has been filled by the FEC and has not already been
allocated and passed up the stack. In this case, the next buffer
in the ring is ready to be allocated. Otherwise, the buffer is
either empty or not empty but still in use by a higher level
protocol. The FEC receive routine uses this function to determine
if multiple buffers where filled by the FEC during a single
interrupt event.
****************************************************************/
return ( !( rx_nbuf[rx_bd_idx].status & RX_BD_E ) );
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright (c) 2006 Christian Walter
* 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.
*
* Note: Most of the network buffer code is based on the MCF5235 examples from
* Freescale.
*
* File: $Id$
*/
#ifndef _NBUF_H
#define _NBUF_H
/* ------------------------ Defines --------------------------------------- */
#ifdef __GNUC__
#define ATTR_FECMEM \
__attribute__((section(".nbuf"),aligned(16)))
#endif
#define NBUF_RX ( 1 )
#define NBUF_TX ( 0 )
/* We set the receiver buffers to the maximum size the FEC supports ( See
* MCF5235 reference manual 19.2.5.1.2 - Driver/DMA Operation with Receive
* BDs). This gives us the benefit that any frame fits into one buffer. A
* maximum size of 2047 is guaranteed by the FEC and 2048 is therefore a
* safe value.
* Note: The value MUST be dividable by 16!
*/
#define RX_BUFFER_SIZE ( 2048 )
/* Size of the transmit buffers. If you set this value to small all frames
* greater than this size will be dropped. The value 1520 was choosen because
* it is bigger than the FEC MTU (1518) and is dividable by 16.
* Note: The value MUST be dividable by 16! */
#define TX_BUFFER_SIZE ( 1520 )
/* Number of Receive and Transmit Buffers and Buffer Descriptors */
#define NUM_RXBDS ( 8 )
#define NUM_TXBDS ( 4 )
/* ------------------------ Defines ( Buffer Descriptor Flags )------------ */
#define TX_BD_R ( 0x8000 )
#define TX_BD_INUSE ( 0x4000 )
#define TX_BD_TO1 ( 0x4000 )
#define TX_BD_W ( 0x2000 )
#define TX_BD_TO2 ( 0x1000 )
#define TX_BD_L ( 0x0800 )
#define TX_BD_TC ( 0x0400 )
#define TX_BD_DEF ( 0x0200 )
#define TX_BD_HB ( 0x0100 )
#define TX_BD_LC ( 0x0080 )
#define TX_BD_RL ( 0x0040 )
#define TX_BD_UN ( 0x0002 )
#define TX_BD_CSL ( 0x0001 )
#define RX_BD_E ( 0x8000 )
#define RX_BD_INUSE ( 0x4000 )
#define RX_BD_R01 ( 0x4000 )
#define RX_BD_W ( 0x2000 )
#define RX_BD_R02 ( 0x1000 )
#define RX_BD_L ( 0x0800 )
#define RX_BD_M ( 0x0100 )
#define RX_BD_BC ( 0x0080 )
#define RX_BD_MC ( 0x0040 )
#define RX_BD_LG ( 0x0020 )
#define RX_BD_NO ( 0x0010 )
#define RX_BD_SH ( 0x0008 )
#define RX_BD_CR ( 0x0004 )
#define RX_BD_OV ( 0x0002 )
#define RX_BD_TR ( 0x0001 )
/* ------------------------ Type definitions ------------------------------ */
typedef struct
{
uint16 status; /* control and status */
uint16 length; /* transfer length */
uint8 *data; /* buffer address */
} nbuf_t;
/* ------------------------ Prototypes ------------------------------------ */
void nbuf_init( void );
uint32 nbuf_get_start( uint8 );
nbuf_t *nbuf_rx_allocate( void );
nbuf_t *nbuf_tx_allocate( void );
void nbuf_rx_release( nbuf_t * );
void nbuf_tx_release( nbuf_t * );
int nbuf_rx_next_ready( void );
#endif

View File

@@ -0,0 +1,562 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Modifications Copyright (c) 2006 Christian Walter <wolti@sil.at>
* 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: Adam Dunkels <adam@sics.se>
* Modifcations: Christian Walter <wolti@sil.at>
*
* $Id$
*/
/* ------------------------ System includes ------------------------------- */
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
/* ------------------------ FreeRTOS includes ----------------------------- */
#include "FreeRTOS.h"
#include "task.h"
#include "serial.h"
#include "semphr.h"
/* ------------------------ lwIP includes --------------------------------- */
#include "lwip/debug.h"
#include "lwip/def.h"
#include "lwip/sys.h"
#include "lwip/mem.h"
#include "lwip/stats.h"
/* ------------------------ Defines --------------------------------------- */
/* This is the number of threads that can be started with sys_thead_new() */
#define SYS_MBOX_SIZE ( 16 )
#define MS_TO_TICKS( ms ) \
( portTickType )( ( portTickType ) ( ms ) / portTICK_RATE_MS )
#define TICKS_TO_MS( ticks ) \
( unsigned portLONG )( ( portTickType ) ( ticks ) * portTICK_RATE_MS )
#define THREAD_STACK_SIZE ( 1024 )
#define THREAD_NAME "lwIP"
/* Must hold the string THREAD_NAME + task number + terminating '\0'. */
#define THREAD_NAME_LEN_MAX 6
#define THREAD_INIT( tcb ) \
do { \
tcb->next = NULL; \
tcb->pid = ( xTaskHandle )0; \
tcb->timeouts.next = NULL; \
memset( tcb->name, 0, THREAD_NAME_LEN_MAX ); \
} while( 0 )
/* ------------------------ Type definitions ------------------------------ */
typedef struct sys_tcb
{
struct sys_tcb *next;
struct sys_timeouts timeouts;
xTaskHandle pid;
char name[THREAD_NAME_LEN_MAX];
} sys_tcb_t;
/* ------------------------ Static functions ------------------------------ */
sys_tcb_t *sys_thread_current( void );
/* ------------------------ Static variables ------------------------------ */
static sys_tcb_t *tasks = NULL;
/* ------------------------ Start implementation -------------------------- */
void
sys_init( void )
{
LWIP_ASSERT( "sys_init: not called first\r\n", tasks == NULL );
tasks = NULL;
}
/*
* This optional function does a "fast" critical region protection and returns
* the previous protection level. This function is only called during very short
* critical regions. An embedded system which supports ISR-based drivers might
* want to implement this function by disabling interrupts. Task-based systems
* might want to implement this by using a mutex or disabling tasking. This
* function should support recursive calls from the same task or interrupt. In
* other words, sys_arch_protect() could be called while already protected. In
* that case the return value indicates that it is already protected.
*
* sys_arch_protect() is only required if your port is supporting an operating
* system.
*/
sys_prot_t
sys_arch_protect( void )
{
vPortEnterCritical( );
return 1;
}
/*
* This optional function does a "fast" set of critical region protection to the
* value specified by pval. See the documentation for sys_arch_protect() for
* more information. This function is only required if your port is supporting
* an operating system.
*/
void
sys_arch_unprotect( sys_prot_t pval )
{
( void )pval;
vPortExitCritical( );
}
/*
* Prints an assertion messages and aborts execution.
*/
void
sys_assert( const char *msg )
{
( void )fputs( msg, stderr );
( void )fputs( "\n\r", stderr );
exit( EXIT_FAILURE );
}
void
sys_debug( const char *const fmt, ... )
{
va_list ap;
va_start( ap, fmt );
( void )vprintf( fmt, ap );
( void )putc( '\r', stdout );
fflush( stdout );
va_end( ap );
}
/* ------------------------ Start implementation ( Threads ) -------------- */
sys_thread_t
sys_thread_new( void ( *thread ) ( void *arg ), void *arg, int prio )
{
return sys_arch_thread_new( thread, arg, prio, THREAD_STACK_SIZE );
}
/*
* Starts a new thread with priority "prio" that will begin its execution in the
* function "thread()". The "arg" argument will be passed as an argument to the
* thread() function. The argument "ssize" is the requested stack size for the
* new thread. The id of the new thread is returned. Both the id and the
* priority are system dependent.
*/
sys_thread_t
sys_arch_thread_new( void ( *thread ) ( void *arg ), void *arg, int prio, size_t ssize )
{
sys_thread_t thread_hdl = SYS_THREAD_NULL;
int i;
sys_tcb_t *p;
/* We disable the FreeRTOS scheduler because it might be the case that the new
* tasks gets scheduled inside the xTaskCreate function. To prevent this we
* disable the scheduling. Note that this can happen although we have interrupts
* disabled because xTaskCreate contains a call to taskYIELD( ).
*/
vPortEnterCritical( );
p = tasks;
i = 0;
/* We are called the first time. Initialize it. */
if( p == NULL )
{
p = pvPortMalloc( sizeof( sys_tcb_t ) );
if( p != NULL )
{
tasks = p;
}
}
else
{
/* First task already counter. */
i++;
/* Cycle to the end of the list. */
while( p->next != NULL )
{
i++;
p = p->next;
}
p->next = pvPortMalloc( sizeof( sys_tcb_t ) );
p = p->next;
}
if( p != NULL )
{
/* Memory allocated. Initialize the data structure. */
THREAD_INIT( p );
( void )snprintf( p->name, THREAD_NAME_LEN_MAX, "lwIP%d", i );
/* Now q points to a free element in the list. */
if( xTaskCreate( thread, p->name, ssize, arg, prio, &p->pid ) == pdPASS )
{
thread_hdl = p;
}
else
{
vPortFree( p );
}
}
vPortExitCritical( );
return thread_hdl;
}
void
sys_arch_thread_remove( sys_thread_t hdl )
{
sys_tcb_t *current = tasks, *prev;
sys_tcb_t *toremove = hdl;
xTaskHandle pid = ( xTaskHandle ) 0;
LWIP_ASSERT( "sys_arch_thread_remove: assertion hdl != NULL failed!", hdl != NULL );
/* If we have to remove the first task we must update the global "tasks"
* variable. */
vPortEnterCritical( );
if( hdl != NULL )
{
prev = NULL;
while( ( current != NULL ) && ( current != toremove ) )
{
prev = current;
current = current->next;
}
/* Found it. */
if( current == toremove )
{
/* Not the first entry in the list. */
if( prev != NULL )
{
prev->next = toremove->next;
}
else
{
tasks = toremove->next;
}
LWIP_ASSERT( "sys_arch_thread_remove: can't remove thread with timeouts!",
toremove->timeouts.next == NULL );
pid = toremove->pid;
THREAD_INIT( toremove );
vPortFree( toremove );
}
}
/* We are done with accessing the shared datastructure. Release the
* resources.
*/
vPortExitCritical( );
if( pid != ( xTaskHandle ) 0 )
{
vTaskDelete( pid );
/* not reached. */
}
}
/*
* Returns the thread control block for the currently active task. In case
* of an error the functions returns NULL.
*/
sys_thread_t
sys_arch_thread_current( void )
{
sys_tcb_t *p = tasks;
xTaskHandle pid = xTaskGetCurrentTaskHandle( );
vPortEnterCritical( );
while( ( p != NULL ) && ( p->pid != pid ) )
{
p = p->next;
}
vPortExitCritical( );
return p;
}
/*
* Returns a pointer to the per-thread sys_timeouts structure. In lwIP,
* each thread has a list of timeouts which is represented as a linked
* list of sys_timeout structures. The sys_timeouts structure holds a
* pointer to a linked list of timeouts. This function is called by
* the lwIP timeout scheduler and must not return a NULL value.
*
* In a single threaded sys_arch implementation, this function will
* simply return a pointer to a global sys_timeouts variable stored in
* the sys_arch module.
*/
struct sys_timeouts *
sys_arch_timeouts( void )
{
sys_tcb_t *ptask;
ptask = sys_arch_thread_current( );
LWIP_ASSERT( "sys_arch_timeouts: ptask != NULL", ptask != NULL );
return ptask != NULL ? &( ptask->timeouts ) : NULL;
}
/* ------------------------ Start implementation ( Semaphores ) ----------- */
/* Creates and returns a new semaphore. The "count" argument specifies
* the initial state of the semaphore.
*/
sys_sem_t
sys_sem_new( u8_t count )
{
xSemaphoreHandle xSemaphore;
vSemaphoreCreateBinary( xSemaphore );
if( xSemaphore != SYS_SEM_NULL )
{
if( count == 0 )
{
xSemaphoreTake( xSemaphore, 1 );
}
#ifdef SYS_STATS
vPortEnterCritical( );
lwip_stats.sys.sem.used++;
if( lwip_stats.sys.sem.used > lwip_stats.sys.sem.max )
{
lwip_stats.sys.sem.max = lwip_stats.sys.sem.used;
}
vPortExitCritical( );
#endif
}
else
{
LWIP_ASSERT( "sys_sem_new: xSemaphore == SYS_SEM_NULL\n", xSemaphore != SYS_SEM_NULL );
}
return xSemaphore;
}
/* Deallocates a semaphore */
void
sys_sem_free( sys_sem_t sem )
{
LWIP_ASSERT( "sys_sem_free: sem != SYS_SEM_NULL\n", sem != SYS_SEM_NULL );
if( sem != SYS_SEM_NULL )
{
#ifdef SYS_STATS
vPortEnterCritical( );
lwip_stats.sys.sem.used--;
vPortExitCritical( );
#endif
vQueueDelete( sem );
}
}
/* Signals a semaphore */
void
sys_sem_signal( sys_sem_t sem )
{
LWIP_ASSERT( "sys_sem_signal: sem != SYS_SEM_NULL\n", sem != SYS_SEM_NULL );
xSemaphoreGive( sem );
}
/*
* Blocks the thread while waiting for the semaphore to be
* signaled. If the "timeout" argument is non-zero, the thread should
* only be blocked for the specified time (measured in
* milliseconds).
*
* If the timeout argument is non-zero, the return value is the number of
* milliseconds spent waiting for the semaphore to be signaled. If the
* semaphore wasn't signaled within the specified time, the return value is
* SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
* (i.e., it was already signaled), the function may return zero.
*
* Notice that lwIP implements a function with a similar name,
* sys_sem_wait(), that uses the sys_arch_sem_wait() function.
*/
u32_t
sys_arch_sem_wait( sys_sem_t sem, u32_t timeout )
{
portBASE_TYPE xStatus;
portTickType xTicksStart, xTicksEnd, xTicksElapsed;
u32_t timespent;
LWIP_ASSERT( "sys_arch_sem_wait: sem != SYS_SEM_NULL", sem != SYS_SEM_NULL );
xTicksStart = xTaskGetTickCount( );
if( timeout == 0 )
{
do
{
xStatus = xSemaphoreTake( sem, MS_TO_TICKS( 100 ) );
}
while( xStatus != pdTRUE );
}
else
{
xStatus = xSemaphoreTake( sem, MS_TO_TICKS( timeout ) );
}
/* Semaphore was signaled. */
if( xStatus == pdTRUE )
{
xTicksEnd = xTaskGetTickCount( );
xTicksElapsed = xTicksEnd - xTicksStart;
timespent = TICKS_TO_MS( xTicksElapsed );
}
else
{
timespent = SYS_ARCH_TIMEOUT;
}
return timespent;
}
/* ------------------------ Start implementation ( Mailboxes ) ------------ */
/* Creates an empty mailbox. */
sys_mbox_t
sys_mbox_new( void )
{
xQueueHandle mbox;
mbox = xQueueCreate( SYS_MBOX_SIZE, sizeof( void * ) );
if( mbox != SYS_MBOX_NULL )
{
#ifdef SYS_STATS
vPortEnterCritical( );
lwip_stats.sys.mbox.used++;
if( lwip_stats.sys.mbox.used > lwip_stats.sys.mbox.max )
{
lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used;
}
vPortExitCritical( );
#endif
}
return mbox;
}
/*
Deallocates a mailbox. If there are messages still present in the
mailbox when the mailbox is deallocated, it is an indication of a
programming error in lwIP and the developer should be notified.
*/
void
sys_mbox_free( sys_mbox_t mbox )
{
void *msg;
LWIP_ASSERT( "sys_mbox_free: mbox != SYS_MBOX_NULL", mbox != SYS_MBOX_NULL );
if( mbox != SYS_MBOX_NULL )
{
while( uxQueueMessagesWaiting( mbox ) != 0 )
{
if( sys_arch_mbox_fetch( mbox, &msg, 1 ) != SYS_ARCH_TIMEOUT )
{
LWIP_ASSERT( "sys_mbox_free: memory leak (msg != NULL)", msg == NULL );
}
}
vQueueDelete( mbox );
#ifdef SYS_STATS
vPortEnterCritical( );
lwip_stats.sys.mbox.used--;
vPortExitCritical( );
#endif
}
}
/*
* This function sends a message to a mailbox. It is unusual in that no error
* return is made. This is because the caller is responsible for ensuring that
* the mailbox queue will not fail. The caller does this by limiting the number
* of msg structures which exist for a given mailbox.
*/
void
sys_mbox_post( sys_mbox_t mbox, void *data )
{
portBASE_TYPE xQueueSent;
/* Queue must not be full - Otherwise it is an error. */
xQueueSent = xQueueSend( mbox, &data, 0 );
LWIP_ASSERT( "sys_mbox_post: xQueueSent == pdPASS", xQueueSent == pdPASS );
}
/*
* Blocks the thread until a message arrives in the mailbox, but does
* not block the thread longer than "timeout" milliseconds (similar to
* the sys_arch_sem_wait() function). The "msg" argument is a result
* parameter that is set by the function (i.e., by doing "*msg =
* ptr"). The "msg" parameter maybe NULL to indicate that the message
* should be dropped.
*
* Note that a function with a similar name, sys_mbox_fetch(), is
* implemented by lwIP.
*/
u32_t
sys_arch_mbox_fetch( sys_mbox_t mbox, void **msg, u32_t timeout )
{
void *ret_msg;
portBASE_TYPE xStatus;
portTickType xTicksStart, xTicksEnd, xTicksElapsed;
u32_t timespent;
LWIP_ASSERT( "sys_arch_mbox_fetch: mbox != SYS_MBOX_NULL", mbox != SYS_MBOX_NULL );
xTicksStart = xTaskGetTickCount( );
if( timeout == 0 )
{
do
{
xStatus = xQueueReceive( mbox, &ret_msg, MS_TO_TICKS( 100 ) );
}
while( xStatus != pdTRUE );
}
else
{
xStatus = xQueueReceive( mbox, &ret_msg, MS_TO_TICKS( timeout ) );
}
if( xStatus == pdTRUE )
{
if( msg )
{
*msg = ret_msg;
}
xTicksEnd = xTaskGetTickCount( );
xTicksElapsed = xTicksEnd - xTicksStart;
timespent = TICKS_TO_MS( xTicksElapsed );
}
else
{
if( msg )
{
*msg = NULL;
}
timespent = SYS_ARCH_TIMEOUT;
}
return timespent;
}
unsigned long
sys_jiffies( void )
{
portTickType xTicks = xTaskGetTickCount( );
return ( unsigned long )TICKS_TO_MS( xTicks );
}

View File

@@ -0,0 +1,62 @@
1 Introduction
This document describes some guidelines for people participating
in lwIP development.
2 How to contribute to lwIP
Here is a short list of suggestions to anybody working with lwIP and
trying to contribute bug reports, fixes, enhancements, platform ports etc.
First of all as you may already know lwIP is a volunteer project so feedback
to fixes or questions might often come late. Hopefully the bug and patch tracking
features of Savannah help us not lose users' input.
2.1 Source code style:
1. do not use tabs.
2. indentation is two spaces per level (i.e. per tab).
3. end debug messages with a trailing newline (\n).
4. one space between keyword and opening bracket.
5. no space between function and opening bracket.
6. one space and no newline before opening curly braces of a block.
7. closing curly brace on a single line.
8. spaces surrounding assignment and comparisons.
9. use current source code style as further reference.
2.2 Source code documentation style:
1. JavaDoc compliant and Doxygen compatible.
2. Function documentation above functions in .c files, not .h files.
(This forces you to synchronize documentation and implementation.)
3. Use current documentation style as further reference.
2.3 Bug reports and patches:
1. Make sure you are reporting bugs or send patches against the latest
sources. (From the latest release and/or the current CVS sources.)
2. If you think you found a bug make sure it's not already filed in the
bugtracker at Savannah.
3. If you have a fix put the patch on Savannah. If it is a patch that affects
both core and arch specific stuff please separate them so that the core can
be applied separately while leaving the other patch 'open'. The prefered way
is to NOT touch archs you can't test and let maintainers take care of them.
This is a good way to see if they are used at all - the same goes for unix
netifs except tapif.
4. Do not file a bug and post a fix to it to the patch area. Either a bug report
or a patch will be enough.
If you correct an existing bug then attach the patch to the bug rather than creating a new entry in the patch area.
5. Trivial patches (compiler warning, indentation and spelling fixes or anything obvious which takes a line or two)
can go to the lwip-users list. This is still the fastest way of interaction and the list is not so crowded
as to allow for loss of fixes. Putting bugs on Savannah and subsequently closing them is too much an overhead
for reporting a compiler warning fix.
6. Patches should be specific to a single change or to related changes.Do not mix bugfixes with spelling and other
trivial fixes unless the bugfix is trivial too.Do not reorganize code and rename identifiers in the same patch you
change behaviour if not necessary.A patch is easier to read and understand if it's to the point and short than
if it's not to the point and long :) so the chances for it to be applied are greater.
2.4 Platform porters:
1. If you have ported lwIP to a platform (an OS, a uC/processor or a combination of these) and
you think it could benefit others[1] you might want discuss this on the mailing list. You
can also ask for CVS access to submit and maintain your port in the contrib CVS module.

View File

@@ -0,0 +1,386 @@
Raw TCP/IP interface for lwIP
Authors: Adam Dunkels, Leon Woestenberg, Christiaan Simons
lwIP provides two Application Program's Interfaces (APIs) for programs
to use for communication with the TCP/IP code:
* low-level "core" / "callback" or "raw" API.
* higher-level "sequential" API.
The sequential API provides a way for ordinary, sequential, programs
to use the lwIP stack. It is quite similar to the BSD socket API. The
model of execution is based on the blocking open-read-write-close
paradigm. Since the TCP/IP stack is event based by nature, the TCP/IP
code and the application program must reside in different execution
contexts (threads).
** The remainder of this document discusses the "raw" API. **
The raw TCP/IP interface allows the application program to integrate
better with the TCP/IP code. Program execution is event based by
having callback functions being called from within the TCP/IP
code. The TCP/IP code and the application program both run in the same
thread. The sequential API has a much higher overhead and is not very
well suited for small systems since it forces a multithreaded paradigm
on the application.
The raw TCP/IP interface is not only faster in terms of code execution
time but is also less memory intensive. The drawback is that program
development is somewhat harder and application programs written for
the raw TCP/IP interface are more difficult to understand. Still, this
is the preferred way of writing applications that should be small in
code size and memory usage.
Both APIs can be used simultaneously by different application
programs. In fact, the sequential API is implemented as an application
program using the raw TCP/IP interface.
--- Callbacks
Program execution is driven by callbacks. Each callback is an ordinary
C function that is called from within the TCP/IP code. Every callback
function is passed the current TCP or UDP connection state as an
argument. Also, in order to be able to keep program specific state,
the callback functions are called with a program specified argument
that is independent of the TCP/IP state.
The function for setting the application connection state is:
- void tcp_arg(struct tcp_pcb *pcb, void *arg)
Specifies the program specific state that should be passed to all
other callback functions. The "pcb" argument is the current TCP
connection control block, and the "arg" argument is the argument
that will be passed to the callbacks.
--- TCP connection setup
The functions used for setting up connections is similar to that of
the sequential API and of the BSD socket API. A new TCP connection
identifier (i.e., a protocol control block - PCB) is created with the
tcp_new() function. This PCB can then be either set to listen for new
incoming connections or be explicitly connected to another host.
- struct tcp_pcb *tcp_new(void)
Creates a new connection identifier (PCB). If memory is not
available for creating the new pcb, NULL is returned.
- err_t tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr,
u16_t port)
Binds the pcb to a local IP address and port number. The IP address
can be specified as IP_ADDR_ANY in order to bind the connection to
all local IP addresses.
If another connection is bound to the same port, the function will
return ERR_USE, otherwise ERR_OK is returned.
- struct tcp_pcb *tcp_listen(struct tcp_pcb *pcb)
Commands a pcb to start listening for incoming connections. When an
incoming connection is accepted, the function specified with the
tcp_accept() function will be called. The pcb will have to be bound
to a local port with the tcp_bind() function.
The tcp_listen() function returns a new connection identifier, and
the one passed as an argument to the function will be
deallocated. The reason for this behavior is that less memory is
needed for a connection that is listening, so tcp_listen() will
reclaim the memory needed for the original connection and allocate a
new smaller memory block for the listening connection.
tcp_listen() may return NULL if no memory was available for the
listening connection. If so, the memory associated with the pcb
passed as an argument to tcp_listen() will not be deallocated.
- void tcp_accept(struct tcp_pcb *pcb,
err_t (* accept)(void *arg, struct tcp_pcb *newpcb,
err_t err))
Specified the callback function that should be called when a new
connection arrives on a listening connection.
- err_t tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr,
u16_t port, err_t (* connected)(void *arg,
struct tcp_pcb *tpcb,
err_t err));
Sets up the pcb to connect to the remote host and sends the
initial SYN segment which opens the connection.
The tcp_connect() function returns immediately; it does not wait for
the connection to be properly setup. Instead, it will call the
function specified as the fourth argument (the "connected" argument)
when the connection is established. If the connection could not be
properly established, either because the other host refused the
connection or because the other host didn't answer, the "connected"
function will be called with an the "err" argument set accordingly.
The tcp_connect() function can return ERR_MEM if no memory is
available for enqueueing the SYN segment. If the SYN indeed was
enqueued successfully, the tcp_connect() function returns ERR_OK.
--- Sending TCP data
TCP data is sent by enqueueing the data with a call to
tcp_write(). When the data is successfully transmitted to the remote
host, the application will be notified with a call to a specified
callback function.
- err_t tcp_write(struct tcp_pcb *pcb, void *dataptr, u16_t len,
u8_t copy)
Enqueues the data pointed to by the argument dataptr. The length of
the data is passed as the len parameter. The copy argument is either
0 or 1 and indicates whether the new memory should be allocated for
the data to be copied into. If the argument is 0, no new memory
should be allocated and the data should only be referenced by
pointer.
The tcp_write() function will fail and return ERR_MEM if the length
of the data exceeds the current send buffer size or if the length of
the queue of outgoing segment is larger than the upper limit defined
in lwipopts.h. The number of bytes available in the output queue can
be retrieved with the tcp_sndbuf() function.
The proper way to use this function is to call the function with at
most tcp_sndbuf() bytes of data. If the function returns ERR_MEM,
the application should wait until some of the currently enqueued
data has been successfully received by the other host and try again.
- void tcp_sent(struct tcp_pcb *pcb,
err_t (* sent)(void *arg, struct tcp_pcb *tpcb,
u16_t len))
Specifies the callback function that should be called when data has
successfully been received (i.e., acknowledged) by the remote
host. The len argument passed to the callback function gives the
amount bytes that was acknowledged by the last acknowledgment.
--- Receiving TCP data
TCP data reception is callback based - an application specified
callback function is called when new data arrives. When the
application has taken the data, it has to call the tcp_recved()
function to indicate that TCP can advertise increase the receive
window.
- void tcp_recv(struct tcp_pcb *pcb,
err_t (* recv)(void *arg, struct tcp_pcb *tpcb,
struct pbuf *p, err_t err))
Sets the callback function that will be called when new data
arrives. The callback function will be passed a NULL pbuf to
indicate that the remote host has closed the connection.
- void tcp_recved(struct tcp_pcb *pcb, u16_t len)
Must be called when the application has received the data. The len
argument indicates the length of the received data.
--- Application polling
When a connection is idle (i.e., no data is either transmitted or
received), lwIP will repeatedly poll the application by calling a
specified callback function. This can be used either as a watchdog
timer for killing connections that have stayed idle for too long, or
as a method of waiting for memory to become available. For instance,
if a call to tcp_write() has failed because memory wasn't available,
the application may use the polling functionality to call tcp_write()
again when the connection has been idle for a while.
- void tcp_poll(struct tcp_pcb *pcb, u8_t interval,
err_t (* poll)(void *arg, struct tcp_pcb *tpcb))
Specifies the polling interval and the callback function that should
be called to poll the application. The interval is specified in
number of TCP coarse grained timer shots, which typically occurs
twice a second. An interval of 10 means that the application would
be polled every 5 seconds.
--- Closing and aborting connections
- err_t tcp_close(struct tcp_pcb *pcb)
Closes the connection. The function may return ERR_MEM if no memory
was available for closing the connection. If so, the application
should wait and try again either by using the acknowledgment
callback or the polling functionality. If the close succeeds, the
function returns ERR_OK.
The pcb is deallocated by the TCP code after a call to tcp_close().
- void tcp_abort(struct tcp_pcb *pcb)
Aborts the connection by sending a RST (reset) segment to the remote
host. The pcb is deallocated. This function never fails.
If a connection is aborted because of an error, the application is
alerted of this event by the err callback. Errors that might abort a
connection are when there is a shortage of memory. The callback
function to be called is set using the tcp_err() function.
- void tcp_err(struct tcp_pcb *pcb, void (* err)(void *arg,
err_t err))
The error callback function does not get the pcb passed to it as a
parameter since the pcb may already have been deallocated.
--- Lower layer TCP interface
TCP provides a simple interface to the lower layers of the
system. During system initialization, the function tcp_init() has
to be called before any other TCP function is called. When the system
is running, the two timer functions tcp_fasttmr() and tcp_slowtmr()
must be called with regular intervals. The tcp_fasttmr() should be
called every TCP_FAST_INTERVAL milliseconds (defined in tcp.h) and
tcp_slowtmr() should be called every TCP_SLOW_INTERVAL milliseconds.
--- UDP interface
The UDP interface is similar to that of TCP, but due to the lower
level of complexity of UDP, the interface is significantly simpler.
- struct udp_pcb *udp_new(void)
Creates a new UDP pcb which can be used for UDP communication. The
pcb is not active until it has either been bound to a local address
or connected to a remote address.
- void udp_remove(struct udp_pcb *pcb)
Removes and deallocates the pcb.
- err_t udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr,
u16_t port)
Binds the pcb to a local address. The IP-address argument "ipaddr"
can be IP_ADDR_ANY to indicate that it should listen to any local IP
address. The function currently always return ERR_OK.
- err_t udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr,
u16_t port)
Sets the remote end of the pcb. This function does not generate any
network traffic, but only set the remote address of the pcb.
- err_t udp_disconnect(struct udp_pcb *pcb)
Remove the remote end of the pcb. This function does not generate
any network traffic, but only removes the remote address of the pcb.
- err_t udp_send(struct udp_pcb *pcb, struct pbuf *p)
Sends the pbuf p. The pbuf is not deallocated.
- void udp_recv(struct udp_pcb *pcb,
void (* recv)(void *arg, struct udp_pcb *upcb,
struct pbuf *p,
struct ip_addr *addr,
u16_t port),
void *recv_arg)
Specifies a callback function that should be called when a UDP
datagram is received.
--- System initalization
A truly complete and generic sequence for initializing the lwip stack
cannot be given because it depends on the build configuration (lwipopts.h)
and additional initializations for your runtime environment (e.g. timers).
We can give you some idea on how to proceed when using the raw API.
We assume a configuration using a single Ethernet netif and the
UDP and TCP transport layers, IPv4 and the DHCP client.
Call these functions in the order of appearance:
- stats_init()
Clears the structure where runtime statistics are gathered.
- sys_init()
Not of much use since we set the NO_SYS 1 option in lwipopts.h,
to be called for easy configuration changes.
- mem_init()
Initializes the dynamic memory heap defined by MEM_SIZE.
- memp_init()
Initializes the memory pools defined by MEMP_NUM_x.
- pbuf_init()
Initializes the pbuf memory pool defined by PBUF_POOL_SIZE.
- etharp_init()
Initializes the ARP table and queue.
Note: you must call etharp_tmr at a 10 second regular interval
after this initialization.
- ip_init()
Doesn't do much, it should be called to handle future changes.
- udp_init()
Clears the UDP PCB list.
- tcp_init()
Clears the TCP PCB list and clears some internal TCP timers.
Note: you must call tcp_fasttmr() and tcp_slowtmr() at the
predefined regular intervals after this initialization.
- netif_add(struct netif *netif, struct ip_addr *ipaddr,
struct ip_addr *netmask, struct ip_addr *gw,
void *state, err_t (* init)(struct netif *netif),
err_t (* input)(struct pbuf *p, struct netif *netif))
Adds your network interface to the netif_list. Allocate a struct
netif and pass a pointer to this structure as the first argument.
Give pointers to cleared ip_addr structures when using DHCP,
or fill them with sane numbers otherwise. The state pointer may be NULL.
The init function pointer must point to a initialization function for
your ethernet netif interface. The following code illustrates it's use.
err_t netif_if_init(struct netif *netif)
{
u8_t i;
for(i = 0; i < 6; i++) netif->hwaddr[i] = some_eth_addr[i];
init_my_eth_device();
return ERR_OK;
}
The input function pointer must point to the lwip ip_input().
- netif_set_default(struct netif *netif)
Registers the default network interface.
- netif_set_up(struct netif *netif)
When the netif is fully configured this function must be called.
- dhcp_start(struct netif *netif)
Creates a new DHCP client for this interface on the first call.
Note: you must call dhcp_fine_tmr() and dhcp_coarse_tmr() at
the predefined regular intervals after starting the client.
You can peek in the netif->dhcp struct for the actual DHCP status.

View File

@@ -0,0 +1,135 @@
Daily Use Guide for using Savannah for lwIP
Table of Contents:
1 - Obtaining lwIP from the CVS repository
2 - Committers/developers CVS access using SSH (to be written)
3 - Merging from DEVEL branch to main trunk (stable branch)
4 - How to release lwIP
1 Obtaining lwIP from the CVS repository
----------------------------------------
To perform an anonymous CVS checkout of the main trunk (this is where
bug fixes and incremental enhancements occur), do this:
cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout lwip
Or, obtain a stable branch (updated with bug fixes only) as follows:
cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \
-r STABLE-0_7 -d lwip-0.7 lwip
Or, obtain a specific (fixed) release as follows:
cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \
-r STABLE-0_7_0 -d lwip-0.7.0 lwip
3 Committers/developers CVS access using SSH
--------------------------------------------
The Savannah server uses SSH (Secure Shell) protocol 2 authentication and encryption.
As such, CVS commits to the server occur through a SSH tunnel for project members.
To create a SSH2 key pair in UNIX-like environments, do this:
ssh-keygen -t dsa
Under Windows, a recommended SSH client is "PuTTY", freely available with good
documentation and a graphic user interface. Use its key generator.
Now paste the id_dsa.pub contents into your Savannah account public key list. Wait
a while so that Savannah can update its configuration (This can take minutes).
Try to login using SSH:
ssh -v your_login@cvs.sv.gnu.org
If it tells you:
Authenticating with public key "your_key_name"...
Server refused to allocate pty
then you could login; Savannah refuses to give you a shell - which is OK, as we
are allowed to use SSH for CVS only. Now, you should be able to do this:
export CVS_RSH=ssh
cvs -z3 -d:ext:your_login@cvs.sv.gnu.org:/sources/lwip co lwip
after which you can edit your local files with bug fixes or new features and
commit them. Make sure you know what you are doing when using CVS to make
changes on the repository. If in doubt, ask on the lwip-members mailing list.
(If SSH asks about authenticity of the host, you can check the key
fingerprint against http://savannah.nongnu.org/cvs/?group=lwip)
3 Merging from DEVEL branch to main trunk (stable)
--------------------------------------------------
Merging is a delicate process in CVS and requires the
following disciplined steps in order to prevent conflicts
in the future. Conflicts can be hard to solve!
Merging from branch A to branch B requires that the A branch
has a tag indicating the previous merger. This tag is called
'merged_from_A_to_B'. After merging, the tag is moved in the
A branch to remember this merger for future merge actions.
IMPORTANT: AFTER COMMITTING A SUCCESFUL MERGE IN THE
REPOSITORY, THE TAG MUST BE SET ON THE SOURCE BRANCH OF THE
MERGE ACTION (REPLACING EXISTING TAGS WITH THE SAME NAME).
Merge all changes in DEVEL since our last merge to main:
In the working copy of the main trunk:
cvs update -P -jmerged_from_DEVEL_to_main -jDEVEL
(This will apply the changes between 'merged_from_DEVEL_to_main'
and 'DEVEL' to your work set of files)
We can now commit the merge result.
cvs commit -R -m "Merged from DEVEL to main."
If this worked out OK, we now move the tag in the DEVEL branch
to this merge point, so we can use this point for future merges:
cvs rtag -F -r DEVEL merged_from_DEVEL_to_main lwip
4 How to release lwIP
---------------------
First, checkout a clean copy of the branch to be released. Tag this set with
tag name "STABLE-0_6_3". (I use release number 0.6.3 throughout this example).
Login CVS using pserver authentication, then export a clean copy of the
tagged tree. Export is similar to a checkout, except that the CVS metadata
is not created locally.
export CVS_RSH=ssh
cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \
-r STABLE-0_6_3 -d lwip-0.6.3 lwip
Archive this directory using tar, gzip'd, bzip2'd and zip'd.
tar czvf lwip-0.6.3.tar.gz lwip-0.6.3
tar cjvf lwip-0.6.3.tar.bz2 lwip-0.6.3
zip -r lwip-0.6.3.zip lwip-0.6.3
Now, sign the archives with a detached GPG binary signature as follows:
gpg -b lwip-0.6.3.tar.gz
gpg -b lwip-0.6.3.tar.bz2
gpg -b lwip-0.6.3.zip
Upload these files using anonymous FTP:
ncftp ftp://savannah.gnu.org/incoming/savannah/lwip
ncftp>mput *0.6.3.*
Additionally, you may post a news item on Savannah, like this:
A new 0.6.3 release is now available here:
http://savannah.nongnu.org/files/?group=lwip&highlight=0.6.3
You will have to submit this via the user News interface, then approve
this via the Administrator News interface.

View File

@@ -0,0 +1,194 @@
sys_arch interface for lwIP 0.6++
Author: Adam Dunkels
The operating system emulation layer provides a common interface
between the lwIP code and the underlying operating system kernel. The
general idea is that porting lwIP to new architectures requires only
small changes to a few header files and a new sys_arch
implementation. It is also possible to do a sys_arch implementation
that does not rely on any underlying operating system.
The sys_arch provides semaphores and mailboxes to lwIP. For the full
lwIP functionality, multiple threads support can be implemented in the
sys_arch, but this is not required for the basic lwIP
functionality. Previous versions of lwIP required the sys_arch to
implement timer scheduling as well but as of lwIP 0.5 this is
implemented in a higher layer.
In addition to the source file providing the functionality of sys_arch,
the OS emulation layer must provide several header files defining
macros used throughout lwip. The files required and the macros they
must define are listed below the sys_arch description.
Semaphores can be either counting or binary - lwIP works with both
kinds. Mailboxes are used for message passing and can be implemented
either as a queue which allows multiple messages to be posted to a
mailbox, or as a rendez-vous point where only one message can be
posted at a time. lwIP works with both kinds, but the former type will
be more efficient. A message in a mailbox is just a pointer, nothing
more.
Semaphores are represented by the type "sys_sem_t" which is typedef'd
in the sys_arch.h file. Mailboxes are equivalently represented by the
type "sys_mbox_t". lwIP does not place any restrictions on how
sys_sem_t or sys_mbox_t are represented internally.
The following functions must be implemented by the sys_arch:
- void sys_init(void)
Is called to initialize the sys_arch layer.
- sys_sem_t sys_sem_new(u8_t count)
Creates and returns a new semaphore. The "count" argument specifies
the initial state of the semaphore.
- void sys_sem_free(sys_sem_t sem)
Deallocates a semaphore.
- void sys_sem_signal(sys_sem_t sem)
Signals a semaphore.
- u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout)
Blocks the thread while waiting for the semaphore to be
signaled. If the "timeout" argument is non-zero, the thread should
only be blocked for the specified time (measured in
milliseconds).
If the timeout argument is non-zero, the return value is the number of
milliseconds spent waiting for the semaphore to be signaled. If the
semaphore wasn't signaled within the specified time, the return value is
SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
(i.e., it was already signaled), the function may return zero.
Notice that lwIP implements a function with a similar name,
sys_sem_wait(), that uses the sys_arch_sem_wait() function.
- sys_mbox_t sys_mbox_new(void)
Creates an empty mailbox.
- void sys_mbox_free(sys_mbox_t mbox)
Deallocates a mailbox. If there are messages still present in the
mailbox when the mailbox is deallocated, it is an indication of a
programming error in lwIP and the developer should be notified.
- void sys_mbox_post(sys_mbox_t mbox, void *msg)
Posts the "msg" to the mailbox.
- u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout)
Blocks the thread until a message arrives in the mailbox, but does
not block the thread longer than "timeout" milliseconds (similar to
the sys_arch_sem_wait() function). The "msg" argument is a result
parameter that is set by the function (i.e., by doing "*msg =
ptr"). The "msg" parameter maybe NULL to indicate that the message
should be dropped.
The return values are the same as for the sys_arch_sem_wait() function:
Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
timeout.
Note that a function with a similar name, sys_mbox_fetch(), is
implemented by lwIP.
- struct sys_timeouts *sys_arch_timeouts(void)
Returns a pointer to the per-thread sys_timeouts structure. In lwIP,
each thread has a list of timeouts which is repressented as a linked
list of sys_timeout structures. The sys_timeouts structure holds a
pointer to a linked list of timeouts. This function is called by
the lwIP timeout scheduler and must not return a NULL value.
In a single threadd sys_arch implementation, this function will
simply return a pointer to a global sys_timeouts variable stored in
the sys_arch module.
If threads are supported by the underlying operating system and if
such functionality is needed in lwIP, the following function will have
to be implemented as well:
- sys_thread_t sys_thread_new(void (* thread)(void *arg), void *arg, int prio)
Starts a new thread with priority "prio" that will begin its execution in the
function "thread()". The "arg" argument will be passed as an argument to the
thread() function. The id of the new thread is returned. Both the id and
the priority are system dependent.
- sys_prot_t sys_arch_protect(void)
This optional function does a "fast" critical region protection and returns
the previous protection level. This function is only called during very short
critical regions. An embedded system which supports ISR-based drivers might
want to implement this function by disabling interrupts. Task-based systems
might want to implement this by using a mutex or disabling tasking. This
function should support recursive calls from the same task or interrupt. In
other words, sys_arch_protect() could be called while already protected. In
that case the return value indicates that it is already protected.
sys_arch_protect() is only required if your port is supporting an operating
system.
- void sys_arch_unprotect(sys_prot_t pval)
This optional function does a "fast" set of critical region protection to the
value specified by pval. See the documentation for sys_arch_protect() for
more information. This function is only required if your port is supporting
an operating system.
-------------------------------------------------------------------------------
Additional files required for the "OS support" emulation layer:
-------------------------------------------------------------------------------
cc.h - Architecture environment, some compiler specific, some
environment specific (probably should move env stuff
to sys_arch.h.)
Typedefs for the types used by lwip -
u8_t, s8_t, u16_t, s16_t, u32_t, s32_t, mem_ptr_t
Compiler hints for packing lwip's structures -
PACK_STRUCT_FIELD(x)
PACK_STRUCT_STRUCT
PACK_STRUCT_BEGIN
PACK_STRUCT_END
Platform specific diagnostic output -
LWIP_PLATFORM_DIAG(x) - non-fatal, print a message.
LWIP_PLATFORM_ASSERT(x) - fatal, print message and abandon execution.
"lightweight" synchronization mechanisms -
SYS_ARCH_DECL_PROTECT(x) - declare a protection state variable.
SYS_ARCH_PROTECT(x) - enter protection mode.
SYS_ARCH_UNPROTECT(x) - leave protection mode.
If the compiler does not provide memset() this file must include a
definition of it, or include a file which defines it.
This file must either include a system-local <errno.h> which defines
the standard *nix error codes, or it should #define LWIP_PROVIDE_ERRNO
to make lwip/arch.h define the codes which are used throughout.
perf.h - Architecture specific performance measurement.
Measurement calls made throughout lwip, these can be defined to nothing.
PERF_START - start measuring something.
PERF_STOP(x) - stop measuring something, and record the result.
sys_arch.h - Tied to sys_arch.c
Arch dependent types for the following objects:
sys_sem_t, sys_mbox_t, sys_thread_t,
And, optionally:
sys_prot_t
Defines to set vars of sys_mbox_t and sys_sem_t to NULL.
SYS_MBOX_NULL NULL
SYS_SEM_NULL NULL

View File

@@ -0,0 +1,13 @@
api/ - The code for the high-level wrapper API. Not needed if
you use the lowel-level call-back/raw API.
core/ - The core of the TPC/IP stack; protocol implementations,
memory and buffer management, and the low-level raw API.
include/ - lwIP include files.
netif/ - Generic network interface device drivers are kept here,
as well as the ARP module.
For more information on the various subdirectories, check the FILES
file in each directory.

View File

@@ -0,0 +1,729 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
/* This is the part of the API that is linked with
the application */
#include "lwip/opt.h"
#include "lwip/api.h"
#include "lwip/api_msg.h"
#include "lwip/memp.h"
struct
netbuf *netbuf_new(void)
{
struct netbuf *buf;
buf = memp_malloc(MEMP_NETBUF);
if (buf != NULL) {
buf->p = NULL;
buf->ptr = NULL;
return buf;
} else {
return NULL;
}
}
void
netbuf_delete(struct netbuf *buf)
{
if (buf != NULL) {
if (buf->p != NULL) {
pbuf_free(buf->p);
buf->p = buf->ptr = NULL;
}
memp_free(MEMP_NETBUF, buf);
}
}
void *
netbuf_alloc(struct netbuf *buf, u16_t size)
{
/* Deallocate any previously allocated memory. */
if (buf->p != NULL) {
pbuf_free(buf->p);
}
buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);
if (buf->p == NULL) {
return NULL;
}
buf->ptr = buf->p;
return buf->p->payload;
}
void
netbuf_free(struct netbuf *buf)
{
if (buf->p != NULL) {
pbuf_free(buf->p);
}
buf->p = buf->ptr = NULL;
}
void
netbuf_ref(struct netbuf *buf, void *dataptr, u16_t size)
{
if (buf->p != NULL) {
pbuf_free(buf->p);
}
buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
buf->p->payload = dataptr;
buf->p->len = buf->p->tot_len = size;
buf->ptr = buf->p;
}
void
netbuf_chain(struct netbuf *head, struct netbuf *tail)
{
pbuf_chain(head->p, tail->p);
head->ptr = head->p;
memp_free(MEMP_NETBUF, tail);
}
u16_t
netbuf_len(struct netbuf *buf)
{
return buf->p->tot_len;
}
err_t
netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
{
if (buf->ptr == NULL) {
return ERR_BUF;
}
*dataptr = buf->ptr->payload;
*len = buf->ptr->len;
return ERR_OK;
}
s8_t
netbuf_next(struct netbuf *buf)
{
if (buf->ptr->next == NULL) {
return -1;
}
buf->ptr = buf->ptr->next;
if (buf->ptr->next == NULL) {
return 1;
}
return 0;
}
void
netbuf_first(struct netbuf *buf)
{
buf->ptr = buf->p;
}
void
netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)
{
struct pbuf *p;
u16_t i, left;
left = 0;
if(buf == NULL || dataptr == NULL) {
return;
}
/* This implementation is bad. It should use bcopy
instead. */
for(p = buf->p; left < len && p != NULL; p = p->next) {
if (offset != 0 && offset >= p->len) {
offset -= p->len;
} else {
for(i = offset; i < p->len; ++i) {
((u8_t *)dataptr)[left] = ((u8_t *)p->payload)[i];
if (++left >= len) {
return;
}
}
offset = 0;
}
}
}
void
netbuf_copy(struct netbuf *buf, void *dataptr, u16_t len)
{
netbuf_copy_partial(buf, dataptr, len, 0);
}
struct ip_addr *
netbuf_fromaddr(struct netbuf *buf)
{
return buf->fromaddr;
}
u16_t
netbuf_fromport(struct netbuf *buf)
{
return buf->fromport;
}
struct
netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto,
void (*callback)(struct netconn *, enum netconn_evt, u16_t len))
{
struct netconn *conn;
struct api_msg *msg;
conn = memp_malloc(MEMP_NETCONN);
if (conn == NULL) {
return NULL;
}
conn->err = ERR_OK;
conn->type = t;
conn->pcb.tcp = NULL;
if ((conn->mbox = sys_mbox_new()) == SYS_MBOX_NULL) {
memp_free(MEMP_NETCONN, conn);
return NULL;
}
conn->recvmbox = SYS_MBOX_NULL;
conn->acceptmbox = SYS_MBOX_NULL;
conn->sem = SYS_SEM_NULL;
conn->state = NETCONN_NONE;
conn->socket = 0;
conn->callback = callback;
conn->recv_avail = 0;
if((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
memp_free(MEMP_NETCONN, conn);
return NULL;
}
msg->type = API_MSG_NEWCONN;
msg->msg.msg.bc.port = proto; /* misusing the port field */
msg->msg.conn = conn;
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
memp_free(MEMP_API_MSG, msg);
if ( conn->err != ERR_OK ) {
memp_free(MEMP_NETCONN, conn);
return NULL;
}
return conn;
}
struct
netconn *netconn_new(enum netconn_type t)
{
return netconn_new_with_proto_and_callback(t,0,NULL);
}
struct
netconn *netconn_new_with_callback(enum netconn_type t,
void (*callback)(struct netconn *, enum netconn_evt, u16_t len))
{
return netconn_new_with_proto_and_callback(t,0,callback);
}
err_t
netconn_delete(struct netconn *conn)
{
struct api_msg *msg;
void *mem;
if (conn == NULL) {
return ERR_OK;
}
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
return ERR_MEM;
}
msg->type = API_MSG_DELCONN;
msg->msg.conn = conn;
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
memp_free(MEMP_API_MSG, msg);
/* Drain the recvmbox. */
if (conn->recvmbox != SYS_MBOX_NULL) {
while (sys_arch_mbox_fetch(conn->recvmbox, &mem, 1) != SYS_ARCH_TIMEOUT) {
if (conn->type == NETCONN_TCP) {
if(mem != NULL)
pbuf_free((struct pbuf *)mem);
} else {
netbuf_delete((struct netbuf *)mem);
}
}
sys_mbox_free(conn->recvmbox);
conn->recvmbox = SYS_MBOX_NULL;
}
/* Drain the acceptmbox. */
if (conn->acceptmbox != SYS_MBOX_NULL) {
while (sys_arch_mbox_fetch(conn->acceptmbox, &mem, 1) != SYS_ARCH_TIMEOUT) {
netconn_delete((struct netconn *)mem);
}
sys_mbox_free(conn->acceptmbox);
conn->acceptmbox = SYS_MBOX_NULL;
}
sys_mbox_free(conn->mbox);
conn->mbox = SYS_MBOX_NULL;
if (conn->sem != SYS_SEM_NULL) {
sys_sem_free(conn->sem);
}
/* conn->sem = SYS_SEM_NULL;*/
memp_free(MEMP_NETCONN, conn);
return ERR_OK;
}
enum netconn_type
netconn_type(struct netconn *conn)
{
return conn->type;
}
err_t
netconn_peer(struct netconn *conn, struct ip_addr *addr,
u16_t *port)
{
switch (conn->type) {
case NETCONN_RAW:
/* return an error as connecting is only a helper for upper layers */
return ERR_CONN;
case NETCONN_UDPLITE:
case NETCONN_UDPNOCHKSUM:
case NETCONN_UDP:
if (conn->pcb.udp == NULL ||
((conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0))
return ERR_CONN;
*addr = (conn->pcb.udp->remote_ip);
*port = conn->pcb.udp->remote_port;
break;
case NETCONN_TCP:
if (conn->pcb.tcp == NULL)
return ERR_CONN;
*addr = (conn->pcb.tcp->remote_ip);
*port = conn->pcb.tcp->remote_port;
break;
}
return (conn->err = ERR_OK);
}
err_t
netconn_addr(struct netconn *conn, struct ip_addr **addr,
u16_t *port)
{
switch (conn->type) {
case NETCONN_RAW:
*addr = &(conn->pcb.raw->local_ip);
*port = conn->pcb.raw->protocol;
break;
case NETCONN_UDPLITE:
case NETCONN_UDPNOCHKSUM:
case NETCONN_UDP:
*addr = &(conn->pcb.udp->local_ip);
*port = conn->pcb.udp->local_port;
break;
case NETCONN_TCP:
*addr = &(conn->pcb.tcp->local_ip);
*port = conn->pcb.tcp->local_port;
break;
}
return (conn->err = ERR_OK);
}
err_t
netconn_bind(struct netconn *conn, struct ip_addr *addr,
u16_t port)
{
struct api_msg *msg;
if (conn == NULL) {
return ERR_VAL;
}
if (conn->type != NETCONN_TCP &&
conn->recvmbox == SYS_MBOX_NULL) {
if ((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
return ERR_MEM;
}
}
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
return (conn->err = ERR_MEM);
}
msg->type = API_MSG_BIND;
msg->msg.conn = conn;
msg->msg.msg.bc.ipaddr = addr;
msg->msg.msg.bc.port = port;
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
memp_free(MEMP_API_MSG, msg);
return conn->err;
}
err_t
netconn_connect(struct netconn *conn, struct ip_addr *addr,
u16_t port)
{
struct api_msg *msg;
if (conn == NULL) {
return ERR_VAL;
}
if (conn->recvmbox == SYS_MBOX_NULL) {
if ((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
return ERR_MEM;
}
}
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
return ERR_MEM;
}
msg->type = API_MSG_CONNECT;
msg->msg.conn = conn;
msg->msg.msg.bc.ipaddr = addr;
msg->msg.msg.bc.port = port;
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
memp_free(MEMP_API_MSG, msg);
return conn->err;
}
err_t
netconn_disconnect(struct netconn *conn)
{
struct api_msg *msg;
if (conn == NULL) {
return ERR_VAL;
}
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
return ERR_MEM;
}
msg->type = API_MSG_DISCONNECT;
msg->msg.conn = conn;
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
memp_free(MEMP_API_MSG, msg);
return conn->err;
}
err_t
netconn_listen(struct netconn *conn)
{
struct api_msg *msg;
if (conn == NULL) {
return ERR_VAL;
}
if (conn->acceptmbox == SYS_MBOX_NULL) {
conn->acceptmbox = sys_mbox_new();
if (conn->acceptmbox == SYS_MBOX_NULL) {
return ERR_MEM;
}
}
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
return (conn->err = ERR_MEM);
}
msg->type = API_MSG_LISTEN;
msg->msg.conn = conn;
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
memp_free(MEMP_API_MSG, msg);
return conn->err;
}
struct netconn *
netconn_accept(struct netconn *conn)
{
struct netconn *newconn;
if (conn == NULL) {
return NULL;
}
sys_mbox_fetch(conn->acceptmbox, (void **)&newconn);
/* Register event with callback */
if (conn->callback)
(*conn->callback)(conn, NETCONN_EVT_RCVMINUS, 0);
return newconn;
}
struct netbuf *
netconn_recv(struct netconn *conn)
{
struct api_msg *msg;
struct netbuf *buf;
struct pbuf *p;
u16_t len;
if (conn == NULL) {
return NULL;
}
if (conn->recvmbox == SYS_MBOX_NULL) {
conn->err = ERR_CONN;
return NULL;
}
if (conn->err != ERR_OK) {
return NULL;
}
if (conn->type == NETCONN_TCP) {
if (conn->pcb.tcp->state == LISTEN) {
conn->err = ERR_CONN;
return NULL;
}
buf = memp_malloc(MEMP_NETBUF);
if (buf == NULL) {
conn->err = ERR_MEM;
return NULL;
}
sys_mbox_fetch(conn->recvmbox, (void **)&p);
if (p != NULL)
{
len = p->tot_len;
conn->recv_avail -= len;
}
else
len = 0;
/* Register event with callback */
if (conn->callback)
(*conn->callback)(conn, NETCONN_EVT_RCVMINUS, len);
/* If we are closed, we indicate that we no longer wish to receive
data by setting conn->recvmbox to SYS_MBOX_NULL. */
if (p == NULL) {
memp_free(MEMP_NETBUF, buf);
sys_mbox_free(conn->recvmbox);
conn->recvmbox = SYS_MBOX_NULL;
return NULL;
}
buf->p = p;
buf->ptr = p;
buf->fromport = 0;
buf->fromaddr = NULL;
/* Let the stack know that we have taken the data. */
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
conn->err = ERR_MEM;
return buf;
}
msg->type = API_MSG_RECV;
msg->msg.conn = conn;
if (buf != NULL) {
msg->msg.msg.len = buf->p->tot_len;
} else {
msg->msg.msg.len = 1;
}
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
memp_free(MEMP_API_MSG, msg);
} else {
sys_mbox_fetch(conn->recvmbox, (void **)&buf);
conn->recv_avail -= buf->p->tot_len;
/* Register event with callback */
if (conn->callback)
(*conn->callback)(conn, NETCONN_EVT_RCVMINUS, buf->p->tot_len);
}
LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv: received %p (err %d)\n", (void *)buf, conn->err));
return buf;
}
err_t
netconn_send(struct netconn *conn, struct netbuf *buf)
{
struct api_msg *msg;
if (conn == NULL) {
return ERR_VAL;
}
if (conn->err != ERR_OK) {
return conn->err;
}
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
return (conn->err = ERR_MEM);
}
LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %d bytes\n", buf->p->tot_len));
msg->type = API_MSG_SEND;
msg->msg.conn = conn;
msg->msg.msg.p = buf->p;
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
memp_free(MEMP_API_MSG, msg);
return conn->err;
}
err_t
netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy)
{
struct api_msg *msg;
u16_t len;
if (conn == NULL) {
return ERR_VAL;
}
if (conn->err != ERR_OK) {
return conn->err;
}
if (conn->sem == SYS_SEM_NULL) {
conn->sem = sys_sem_new(0);
if (conn->sem == SYS_SEM_NULL) {
return ERR_MEM;
}
}
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
return (conn->err = ERR_MEM);
}
msg->type = API_MSG_WRITE;
msg->msg.conn = conn;
conn->state = NETCONN_WRITE;
while (conn->err == ERR_OK && size > 0) {
msg->msg.msg.w.dataptr = dataptr;
msg->msg.msg.w.copy = copy;
if (conn->type == NETCONN_TCP) {
if (tcp_sndbuf(conn->pcb.tcp) == 0) {
sys_sem_wait(conn->sem);
if (conn->err != ERR_OK) {
goto ret;
}
}
if (size > tcp_sndbuf(conn->pcb.tcp)) {
/* We cannot send more than one send buffer's worth of data at a
time. */
len = tcp_sndbuf(conn->pcb.tcp);
} else {
len = size;
}
} else {
len = size;
}
LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_write: writing %d bytes (%d)\n", len, copy));
msg->msg.msg.w.len = len;
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
if (conn->err == ERR_OK) {
dataptr = (void *)((u8_t *)dataptr + len);
size -= len;
} else if (conn->err == ERR_MEM) {
conn->err = ERR_OK;
sys_sem_wait(conn->sem);
} else {
goto ret;
}
}
ret:
memp_free(MEMP_API_MSG, msg);
conn->state = NETCONN_NONE;
if (conn->sem != SYS_SEM_NULL) {
sys_sem_free(conn->sem);
conn->sem = SYS_SEM_NULL;
}
return conn->err;
}
err_t
netconn_close(struct netconn *conn)
{
struct api_msg *msg;
if (conn == NULL) {
return ERR_VAL;
}
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
return (conn->err = ERR_MEM);
}
conn->state = NETCONN_CLOSE;
again:
msg->type = API_MSG_CLOSE;
msg->msg.conn = conn;
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
if (conn->err == ERR_MEM &&
conn->sem != SYS_SEM_NULL) {
sys_sem_wait(conn->sem);
goto again;
}
conn->state = NETCONN_NONE;
memp_free(MEMP_API_MSG, msg);
return conn->err;
}
err_t
netconn_err(struct netconn *conn)
{
return conn->err;
}

View File

@@ -0,0 +1,800 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/opt.h"
#include "lwip/arch.h"
#include "lwip/api_msg.h"
#include "lwip/memp.h"
#include "lwip/sys.h"
#include "lwip/tcpip.h"
#if LWIP_RAW
static u8_t
recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
struct ip_addr *addr)
{
struct netbuf *buf;
struct netconn *conn;
conn = arg;
if (!conn) return 0;
if (conn->recvmbox != SYS_MBOX_NULL) {
if (!(buf = memp_malloc(MEMP_NETBUF))) {
return 0;
}
pbuf_ref(p);
buf->p = p;
buf->ptr = p;
buf->fromaddr = addr;
buf->fromport = pcb->protocol;
conn->recv_avail += p->tot_len;
/* Register event with callback */
if (conn->callback)
(*conn->callback)(conn, NETCONN_EVT_RCVPLUS, p->tot_len);
sys_mbox_post(conn->recvmbox, buf);
}
return 0; /* do not eat the packet */
}
#endif
#if LWIP_UDP
static void
recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
struct ip_addr *addr, u16_t port)
{
struct netbuf *buf;
struct netconn *conn;
conn = arg;
if (conn == NULL) {
pbuf_free(p);
return;
}
if (conn->recvmbox != SYS_MBOX_NULL) {
buf = memp_malloc(MEMP_NETBUF);
if (buf == NULL) {
pbuf_free(p);
return;
} else {
buf->p = p;
buf->ptr = p;
buf->fromaddr = addr;
buf->fromport = port;
}
conn->recv_avail += p->tot_len;
/* Register event with callback */
if (conn->callback)
(*conn->callback)(conn, NETCONN_EVT_RCVPLUS, p->tot_len);
sys_mbox_post(conn->recvmbox, buf);
}
}
#endif /* LWIP_UDP */
#if LWIP_TCP
static err_t
recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
struct netconn *conn;
u16_t len;
conn = arg;
if (conn == NULL) {
pbuf_free(p);
return ERR_VAL;
}
if (conn->recvmbox != SYS_MBOX_NULL) {
conn->err = err;
if (p != NULL) {
len = p->tot_len;
conn->recv_avail += len;
}
else
len = 0;
/* Register event with callback */
if (conn->callback)
(*conn->callback)(conn, NETCONN_EVT_RCVPLUS, len);
sys_mbox_post(conn->recvmbox, p);
}
return ERR_OK;
}
static err_t
poll_tcp(void *arg, struct tcp_pcb *pcb)
{
struct netconn *conn;
conn = arg;
if (conn != NULL &&
(conn->state == NETCONN_WRITE || conn->state == NETCONN_CLOSE) &&
conn->sem != SYS_SEM_NULL) {
sys_sem_signal(conn->sem);
}
return ERR_OK;
}
static err_t
sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
{
struct netconn *conn;
conn = arg;
if (conn != NULL && conn->sem != SYS_SEM_NULL) {
sys_sem_signal(conn->sem);
}
if (conn && conn->callback)
if (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT)
(*conn->callback)(conn, NETCONN_EVT_SENDPLUS, len);
return ERR_OK;
}
static void
err_tcp(void *arg, err_t err)
{
struct netconn *conn;
conn = arg;
conn->pcb.tcp = NULL;
conn->err = err;
if (conn->recvmbox != SYS_MBOX_NULL) {
/* Register event with callback */
if (conn->callback)
(*conn->callback)(conn, NETCONN_EVT_RCVPLUS, 0);
sys_mbox_post(conn->recvmbox, NULL);
}
if (conn->mbox != SYS_MBOX_NULL) {
sys_mbox_post(conn->mbox, NULL);
}
if (conn->acceptmbox != SYS_MBOX_NULL) {
/* Register event with callback */
if (conn->callback)
(*conn->callback)(conn, NETCONN_EVT_RCVPLUS, 0);
sys_mbox_post(conn->acceptmbox, NULL);
}
if (conn->sem != SYS_SEM_NULL) {
sys_sem_signal(conn->sem);
}
}
static void
setup_tcp(struct netconn *conn)
{
struct tcp_pcb *pcb;
pcb = conn->pcb.tcp;
tcp_arg(pcb, conn);
tcp_recv(pcb, recv_tcp);
tcp_sent(pcb, sent_tcp);
tcp_poll(pcb, poll_tcp, 4);
tcp_err(pcb, err_tcp);
}
static err_t
accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
{
sys_mbox_t mbox;
struct netconn *newconn;
struct netconn *conn;
#if API_MSG_DEBUG
#if TCP_DEBUG
tcp_debug_print_state(newpcb->state);
#endif /* TCP_DEBUG */
#endif /* API_MSG_DEBUG */
conn = (struct netconn *)arg;
mbox = conn->acceptmbox;
newconn = memp_malloc(MEMP_NETCONN);
if (newconn == NULL) {
return ERR_MEM;
}
newconn->type = NETCONN_TCP;
newconn->pcb.tcp = newpcb;
setup_tcp(newconn);
newconn->recvmbox = sys_mbox_new();
if (newconn->recvmbox == SYS_MBOX_NULL) {
memp_free(MEMP_NETCONN, newconn);
return ERR_MEM;
}
newconn->mbox = sys_mbox_new();
if (newconn->mbox == SYS_MBOX_NULL) {
sys_mbox_free(newconn->recvmbox);
memp_free(MEMP_NETCONN, newconn);
return ERR_MEM;
}
newconn->sem = sys_sem_new(0);
if (newconn->sem == SYS_SEM_NULL) {
sys_mbox_free(newconn->recvmbox);
sys_mbox_free(newconn->mbox);
memp_free(MEMP_NETCONN, newconn);
return ERR_MEM;
}
newconn->acceptmbox = SYS_MBOX_NULL;
newconn->err = err;
/* Register event with callback */
if (conn->callback)
{
(*conn->callback)(conn, NETCONN_EVT_RCVPLUS, 0);
/* We have to set the callback here even though
* the new socket is unknown. Mark the socket as -1. */
newconn->callback = conn->callback;
newconn->socket = -1;
}
sys_mbox_post(mbox, newconn);
return ERR_OK;
}
#endif /* LWIP_TCP */
static void
do_newconn(struct api_msg_msg *msg)
{
if(msg->conn->pcb.tcp != NULL) {
/* This "new" connection already has a PCB allocated. */
/* Is this an error condition? Should it be deleted?
We currently just are happy and return. */
sys_mbox_post(msg->conn->mbox, NULL);
return;
}
msg->conn->err = ERR_OK;
/* Allocate a PCB for this connection */
switch(msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field */
raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
msg->conn->pcb.udp = udp_new();
if(msg->conn->pcb.udp == NULL) {
msg->conn->err = ERR_MEM;
break;
}
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
break;
case NETCONN_UDPNOCHKSUM:
msg->conn->pcb.udp = udp_new();
if(msg->conn->pcb.udp == NULL) {
msg->conn->err = ERR_MEM;
break;
}
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
break;
case NETCONN_UDP:
msg->conn->pcb.udp = udp_new();
if(msg->conn->pcb.udp == NULL) {
msg->conn->err = ERR_MEM;
break;
}
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
break;
#endif /* LWIP_UDP */
#if LWIP_TCP
case NETCONN_TCP:
msg->conn->pcb.tcp = tcp_new();
if(msg->conn->pcb.tcp == NULL) {
msg->conn->err = ERR_MEM;
break;
}
setup_tcp(msg->conn);
break;
#endif
}
sys_mbox_post(msg->conn->mbox, NULL);
}
static void
do_delconn(struct api_msg_msg *msg)
{
if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
raw_remove(msg->conn->pcb.raw);
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
case NETCONN_UDPNOCHKSUM:
/* FALLTHROUGH */
case NETCONN_UDP:
msg->conn->pcb.udp->recv_arg = NULL;
udp_remove(msg->conn->pcb.udp);
break;
#endif /* LWIP_UDP */
#if LWIP_TCP
case NETCONN_TCP:
if (msg->conn->pcb.tcp->state == LISTEN) {
tcp_arg(msg->conn->pcb.tcp, NULL);
tcp_accept(msg->conn->pcb.tcp, NULL);
tcp_close(msg->conn->pcb.tcp);
} else {
tcp_arg(msg->conn->pcb.tcp, NULL);
tcp_sent(msg->conn->pcb.tcp, NULL);
tcp_recv(msg->conn->pcb.tcp, NULL);
tcp_poll(msg->conn->pcb.tcp, NULL, 0);
tcp_err(msg->conn->pcb.tcp, NULL);
if (tcp_close(msg->conn->pcb.tcp) != ERR_OK) {
tcp_abort(msg->conn->pcb.tcp);
}
}
#endif
default:
break;
}
}
/* Trigger select() in socket layer */
if (msg->conn->callback)
{
(*msg->conn->callback)(msg->conn, NETCONN_EVT_RCVPLUS, 0);
(*msg->conn->callback)(msg->conn, NETCONN_EVT_SENDPLUS, 0);
}
if (msg->conn->mbox != SYS_MBOX_NULL) {
sys_mbox_post(msg->conn->mbox, NULL);
}
}
static void
do_bind(struct api_msg_msg *msg)
{
if (msg->conn->pcb.tcp == NULL) {
switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field as protocol */
raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
msg->conn->pcb.udp = udp_new();
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
break;
case NETCONN_UDPNOCHKSUM:
msg->conn->pcb.udp = udp_new();
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
break;
case NETCONN_UDP:
msg->conn->pcb.udp = udp_new();
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
break;
#endif /* LWIP_UDP */
#if LWIP_TCP
case NETCONN_TCP:
msg->conn->pcb.tcp = tcp_new();
setup_tcp(msg->conn);
#endif /* LWIP_TCP */
default:
break;
}
}
switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
msg->conn->err = raw_bind(msg->conn->pcb.raw,msg->msg.bc.ipaddr);
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
case NETCONN_UDPNOCHKSUM:
/* FALLTHROUGH */
case NETCONN_UDP:
msg->conn->err = udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
break;
#endif /* LWIP_UDP */
#if LWIP_TCP
case NETCONN_TCP:
msg->conn->err = tcp_bind(msg->conn->pcb.tcp,
msg->msg.bc.ipaddr, msg->msg.bc.port);
#endif /* LWIP_TCP */
default:
break;
}
sys_mbox_post(msg->conn->mbox, NULL);
}
#if LWIP_TCP
static err_t
do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
{
struct netconn *conn;
conn = arg;
if (conn == NULL) {
return ERR_VAL;
}
conn->err = err;
if (conn->type == NETCONN_TCP && err == ERR_OK) {
setup_tcp(conn);
}
sys_mbox_post(conn->mbox, NULL);
return ERR_OK;
}
#endif
static void
do_connect(struct api_msg_msg *msg)
{
if (msg->conn->pcb.tcp == NULL) {
switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field as protocol */
raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
msg->conn->pcb.udp = udp_new();
if (msg->conn->pcb.udp == NULL) {
msg->conn->err = ERR_MEM;
sys_mbox_post(msg->conn->mbox, NULL);
return;
}
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
break;
case NETCONN_UDPNOCHKSUM:
msg->conn->pcb.udp = udp_new();
if (msg->conn->pcb.udp == NULL) {
msg->conn->err = ERR_MEM;
sys_mbox_post(msg->conn->mbox, NULL);
return;
}
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
break;
case NETCONN_UDP:
msg->conn->pcb.udp = udp_new();
if (msg->conn->pcb.udp == NULL) {
msg->conn->err = ERR_MEM;
sys_mbox_post(msg->conn->mbox, NULL);
return;
}
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
break;
#endif /* LWIP_UDP */
#if LWIP_TCP
case NETCONN_TCP:
msg->conn->pcb.tcp = tcp_new();
if (msg->conn->pcb.tcp == NULL) {
msg->conn->err = ERR_MEM;
sys_mbox_post(msg->conn->mbox, NULL);
return;
}
#endif
default:
break;
}
}
switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr);
sys_mbox_post(msg->conn->mbox, NULL);
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
case NETCONN_UDPNOCHKSUM:
/* FALLTHROUGH */
case NETCONN_UDP:
udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
sys_mbox_post(msg->conn->mbox, NULL);
break;
#endif
#if LWIP_TCP
case NETCONN_TCP:
/* tcp_arg(msg->conn->pcb.tcp, msg->conn);*/
setup_tcp(msg->conn);
tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port,
do_connected);
/*tcp_output(msg->conn->pcb.tcp);*/
#endif
default:
break;
}
}
static void
do_disconnect(struct api_msg_msg *msg)
{
switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
/* Do nothing as connecting is only a helper for upper lwip layers */
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
case NETCONN_UDPNOCHKSUM:
/* FALLTHROUGH */
case NETCONN_UDP:
udp_disconnect(msg->conn->pcb.udp);
break;
#endif
case NETCONN_TCP:
break;
}
sys_mbox_post(msg->conn->mbox, NULL);
}
static void
do_listen(struct api_msg_msg *msg)
{
if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen RAW: cannot listen for RAW.\n"));
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
case NETCONN_UDPNOCHKSUM:
/* FALLTHROUGH */
case NETCONN_UDP:
LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen UDP: cannot listen for UDP.\n"));
break;
#endif /* LWIP_UDP */
#if LWIP_TCP
case NETCONN_TCP:
msg->conn->pcb.tcp = tcp_listen(msg->conn->pcb.tcp);
if (msg->conn->pcb.tcp == NULL) {
msg->conn->err = ERR_MEM;
} else {
if (msg->conn->acceptmbox == SYS_MBOX_NULL) {
msg->conn->acceptmbox = sys_mbox_new();
if (msg->conn->acceptmbox == SYS_MBOX_NULL) {
msg->conn->err = ERR_MEM;
break;
}
}
tcp_arg(msg->conn->pcb.tcp, msg->conn);
tcp_accept(msg->conn->pcb.tcp, accept_function);
}
#endif
default:
break;
}
}
sys_mbox_post(msg->conn->mbox, NULL);
}
static void
do_accept(struct api_msg_msg *msg)
{
if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: accept RAW: cannot accept for RAW.\n"));
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
case NETCONN_UDPNOCHKSUM:
/* FALLTHROUGH */
case NETCONN_UDP:
LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: accept UDP: cannot accept for UDP.\n"));
break;
#endif /* LWIP_UDP */
case NETCONN_TCP:
break;
}
}
}
static void
do_send(struct api_msg_msg *msg)
{
if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
raw_send(msg->conn->pcb.raw, msg->msg.p);
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
case NETCONN_UDPNOCHKSUM:
/* FALLTHROUGH */
case NETCONN_UDP:
udp_send(msg->conn->pcb.udp, msg->msg.p);
break;
#endif /* LWIP_UDP */
case NETCONN_TCP:
break;
}
}
sys_mbox_post(msg->conn->mbox, NULL);
}
static void
do_recv(struct api_msg_msg *msg)
{
#if LWIP_TCP
if (msg->conn->pcb.tcp != NULL) {
if (msg->conn->type == NETCONN_TCP) {
tcp_recved(msg->conn->pcb.tcp, msg->msg.len);
}
}
#endif
sys_mbox_post(msg->conn->mbox, NULL);
}
static void
do_write(struct api_msg_msg *msg)
{
#if LWIP_TCP
err_t err;
#endif
if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
msg->conn->err = ERR_VAL;
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
case NETCONN_UDPNOCHKSUM:
/* FALLTHROUGH */
case NETCONN_UDP:
msg->conn->err = ERR_VAL;
break;
#endif /* LWIP_UDP */
#if LWIP_TCP
case NETCONN_TCP:
err = tcp_write(msg->conn->pcb.tcp, msg->msg.w.dataptr,
msg->msg.w.len, msg->msg.w.copy);
/* This is the Nagle algorithm: inhibit the sending of new TCP
segments when new outgoing data arrives from the user if any
previously transmitted data on the connection remains
unacknowledged. */
if(err == ERR_OK && (msg->conn->pcb.tcp->unacked == NULL || (msg->conn->pcb.tcp->flags & TF_NODELAY)) ) {
tcp_output(msg->conn->pcb.tcp);
}
msg->conn->err = err;
if (msg->conn->callback)
if (err == ERR_OK)
{
if (tcp_sndbuf(msg->conn->pcb.tcp) <= TCP_SNDLOWAT)
(*msg->conn->callback)(msg->conn, NETCONN_EVT_SENDMINUS, msg->msg.w.len);
}
#endif
default:
break;
}
}
sys_mbox_post(msg->conn->mbox, NULL);
}
static void
do_close(struct api_msg_msg *msg)
{
err_t err;
err = ERR_OK;
if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
case NETCONN_UDPNOCHKSUM:
/* FALLTHROUGH */
case NETCONN_UDP:
break;
#endif /* LWIP_UDP */
#if LWIP_TCP
case NETCONN_TCP:
if (msg->conn->pcb.tcp->state == LISTEN) {
err = tcp_close(msg->conn->pcb.tcp);
}
msg->conn->err = err;
#endif
default:
break;
}
}
sys_mbox_post(msg->conn->mbox, NULL);
}
typedef void (* api_msg_decode)(struct api_msg_msg *msg);
static api_msg_decode decode[API_MSG_MAX] = {
do_newconn,
do_delconn,
do_bind,
do_connect,
do_disconnect,
do_listen,
do_accept,
do_send,
do_recv,
do_write,
do_close
};
void
api_msg_input(struct api_msg *msg)
{
decode[msg->type](&(msg->msg));
}
void
api_msg_post(struct api_msg *msg)
{
tcpip_apimsg(msg);
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/err.h"
#ifdef LWIP_DEBUG
static char *err_strerr[] = {"Ok.",
"Out of memory error.",
"Buffer error.",
"Connection aborted.",
"Connection reset.",
"Connection closed.",
"Not connected.",
"Illegal value.",
"Illegal argument.",
"Routing problem.",
"Address in use."
};
char *
lwip_strerr(err_t err)
{
return err_strerr[-err];
}
#endif /* LWIP_DEBUG */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,198 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/opt.h"
#include "lwip/sys.h"
#include "lwip/memp.h"
#include "lwip/pbuf.h"
#include "lwip/ip.h"
#include "lwip/ip_frag.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
#include "lwip/tcpip.h"
static void (* tcpip_init_done)(void *arg) = NULL;
static void *tcpip_init_done_arg;
static sys_mbox_t mbox;
#if LWIP_TCP
static int tcpip_tcp_timer_active = 0;
static void
tcpip_tcp_timer(void *arg)
{
(void)arg;
/* call TCP timer handler */
tcp_tmr();
/* timer still needed? */
if (tcp_active_pcbs || tcp_tw_pcbs) {
/* restart timer */
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
} else {
/* disable timer */
tcpip_tcp_timer_active = 0;
}
}
#if !NO_SYS
void
tcp_timer_needed(void)
{
/* timer is off but needed again? */
if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
/* enable and start timer */
tcpip_tcp_timer_active = 1;
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
}
}
#endif /* !NO_SYS */
#endif /* LWIP_TCP */
#if IP_REASSEMBLY
static void
ip_timer(void *data)
{
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: ip_reass_tmr()\n"));
ip_reass_tmr();
sys_timeout(1000, ip_timer, NULL);
}
#endif
static void
tcpip_thread(void *arg)
{
struct tcpip_msg *msg;
(void)arg;
ip_init();
#if LWIP_UDP
udp_init();
#endif
#if LWIP_TCP
tcp_init();
#endif
#if IP_REASSEMBLY
sys_timeout(1000, ip_timer, NULL);
#endif
if (tcpip_init_done != NULL) {
tcpip_init_done(tcpip_init_done_arg);
}
while (1) { /* MAIN Loop */
sys_mbox_fetch(mbox, (void *)&msg);
switch (msg->type) {
case TCPIP_MSG_API:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg));
api_msg_input(msg->msg.apimsg);
break;
case TCPIP_MSG_INPUT:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: IP packet %p\n", (void *)msg));
ip_input(msg->msg.inp.p, msg->msg.inp.netif);
break;
case TCPIP_MSG_CALLBACK:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
msg->msg.cb.f(msg->msg.cb.ctx);
break;
default:
break;
}
memp_free(MEMP_TCPIP_MSG, msg);
}
}
err_t
tcpip_input(struct pbuf *p, struct netif *inp)
{
struct tcpip_msg *msg;
msg = memp_malloc(MEMP_TCPIP_MSG);
if (msg == NULL) {
pbuf_free(p);
return ERR_MEM;
}
msg->type = TCPIP_MSG_INPUT;
msg->msg.inp.p = p;
msg->msg.inp.netif = inp;
sys_mbox_post(mbox, msg);
return ERR_OK;
}
err_t
tcpip_callback(void (*f)(void *ctx), void *ctx)
{
struct tcpip_msg *msg;
msg = memp_malloc(MEMP_TCPIP_MSG);
if (msg == NULL) {
return ERR_MEM;
}
msg->type = TCPIP_MSG_CALLBACK;
msg->msg.cb.f = f;
msg->msg.cb.ctx = ctx;
sys_mbox_post(mbox, msg);
return ERR_OK;
}
void
tcpip_apimsg(struct api_msg *apimsg)
{
struct tcpip_msg *msg;
msg = memp_malloc(MEMP_TCPIP_MSG);
if (msg == NULL) {
memp_free(MEMP_API_MSG, apimsg);
return;
}
msg->type = TCPIP_MSG_API;
msg->msg.apimsg = apimsg;
sys_mbox_post(mbox, msg);
}
void
tcpip_init(void (* initfunc)(void *), void *arg)
{
tcpip_init_done = initfunc;
tcpip_init_done_arg = arg;
mbox = sys_mbox_new();
sys_thread_new(tcpip_thread, NULL, TCPIP_THREAD_PRIO);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,525 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
/* inet.c
*
* Functions common to all TCP/IP modules, such as the Internet checksum and the
* byte order functions.
*
*/
#include "lwip/opt.h"
#include "lwip/arch.h"
#include "lwip/def.h"
#include "lwip/inet.h"
#include "lwip/sys.h"
/* This is a reference implementation of the checksum algorithm, with the
* aim of being simple, correct and fully portable. Checksumming is the
* first thing you would want to optimize for your platform. You will
* need to port it to your architecture and in your sys_arch.h:
*
* #define LWIP_CHKSUM <your_checksum_routine>
*/
#ifndef LWIP_CHKSUM
#define LWIP_CHKSUM lwip_standard_chksum
/**
* lwip checksum
*
* @param dataptr points to start of data to be summed at any boundary
* @param len length of data to be summed
* @return host order (!) lwip checksum (non-inverted Internet sum)
*
* @note accumulator size limits summable lenght to 64k
* @note host endianess is irrelevant (p3 RFC1071)
*/
static u16_t
lwip_standard_chksum(void *dataptr, u16_t len)
{
u32_t acc;
u16_t src;
u8_t *octetptr;
acc = 0;
/* dataptr may be at odd or even addresses */
octetptr = (u8_t*)dataptr;
while (len > 1)
{
/* declare first octet as most significant
thus assume network order, ignoring host order */
src = (*octetptr) << 8;
octetptr++;
/* declare second octet as least significant */
src |= (*octetptr);
octetptr++;
acc += src;
len -= 2;
}
if (len > 0)
{
/* accumulate remaining octet */
src = (*octetptr) << 8;
acc += src;
}
/* add deferred carry bits */
acc = (acc >> 16) + (acc & 0x0000ffffUL);
if ((acc & 0xffff0000) != 0) {
acc = (acc >> 16) + (acc & 0x0000ffffUL);
}
/* This maybe a little confusing: reorder sum using htons()
instead of ntohs() since it has a little less call overhead.
The caller must invert bits for Internet sum ! */
return htons((u16_t)acc);
}
#endif
#if 0
/*
* Curt McDowell
* Broadcom Corp.
* csm@broadcom.com
*
* IP checksum two bytes at a time with support for
* unaligned buffer.
* Works for len up to and including 0x20000.
* by Curt McDowell, Broadcom Corp. 12/08/2005
*/
static u16_t
lwip_standard_chksum2(void *dataptr, int len)
{
u8_t *pb = dataptr;
u16_t *ps, t = 0;
u32_t sum = 0;
int odd = ((u32_t)pb & 1);
/* Get aligned to u16_t */
if (odd && len > 0) {
((u8_t *)&t)[1] = *pb++;
len--;
}
/* Add the bulk of the data */
ps = (u16_t *)pb;
while (len > 1) {
sum += *ps++;
len -= 2;
}
/* Consume left-over byte, if any */
if (len > 0)
((u8_t *)&t)[0] = *(u8_t *)ps;;
/* Add end bytes */
sum += t;
/* Fold 32-bit sum to 16 bits */
while (sum >> 16)
sum = (sum & 0xffff) + (sum >> 16);
/* Swap if alignment was odd */
if (odd)
sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
return sum;
}
/**
* An optimized checksum routine. Basically, it uses loop-unrolling on
* the checksum loop, treating the head and tail bytes specially, whereas
* the inner loop acts on 8 bytes at a time.
*
* @arg start of buffer to be checksummed. May be an odd byte address.
* @len number of bytes in the buffer to be checksummed.
*
* @todo First argument type conflicts with generic checksum routine.
*
* by Curt McDowell, Broadcom Corp. December 8th, 2005
*/
static u16_t
lwip_standard_chksum4(u8_t *pb, int len)
{
u16_t *ps, t = 0;
u32_t *pl;
u32_t sum = 0, tmp;
/* starts at odd byte address? */
int odd = ((u32_t)pb & 1);
if (odd && len > 0) {
((u8_t *)&t)[1] = *pb++;
len--;
}
ps = (u16_t *)pb;
if (((u32_t)ps & 3) && len > 1) {
sum += *ps++;
len -= 2;
}
pl = (u32_t *)ps;
while (len > 7) {
tmp = sum + *pl++; /* ping */
if (tmp < sum)
tmp++; /* add back carry */
sum = tmp + *pl++; /* pong */
if (sum < tmp)
sum++; /* add back carry */
len -= 8;
}
/* make room in upper bits */
sum = (sum >> 16) + (sum & 0xffff);
ps = (u16_t *)pl;
/* 16-bit aligned word remaining? */
while (len > 1) {
sum += *ps++;
len -= 2;
}
/* dangling tail byte remaining? */
if (len > 0) /* include odd byte */
((u8_t *)&t)[0] = *(u8_t *)ps;
sum += t; /* add end bytes */
while (sum >> 16) /* combine halves */
sum = (sum >> 16) + (sum & 0xffff);
if (odd)
sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
return sum;
}
#endif
/* inet_chksum_pseudo:
*
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
*/
u16_t
inet_chksum_pseudo(struct pbuf *p,
struct ip_addr *src, struct ip_addr *dest,
u8_t proto, u16_t proto_len)
{
u32_t acc;
struct pbuf *q;
u8_t swapped;
acc = 0;
swapped = 0;
/* iterate through all pbuf in chain */
for(q = p; q != NULL; q = q->next) {
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
(void *)q, (void *)q->next));
acc += LWIP_CHKSUM(q->payload, q->len);
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
while (acc >> 16) {
acc = (acc & 0xffffUL) + (acc >> 16);
}
if (q->len % 2 != 0) {
swapped = 1 - swapped;
acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
}
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
}
if (swapped) {
acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
}
acc += (src->addr & 0xffffUL);
acc += ((src->addr >> 16) & 0xffffUL);
acc += (dest->addr & 0xffffUL);
acc += ((dest->addr >> 16) & 0xffffUL);
acc += (u32_t)htons((u16_t)proto);
acc += (u32_t)htons(proto_len);
while (acc >> 16) {
acc = (acc & 0xffffUL) + (acc >> 16);
}
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
return (u16_t)~(acc & 0xffffUL);
}
/* inet_chksum:
*
* Calculates the Internet checksum over a portion of memory. Used primarely for IP
* and ICMP.
*/
u16_t
inet_chksum(void *dataptr, u16_t len)
{
u32_t acc;
acc = LWIP_CHKSUM(dataptr, len);
while (acc >> 16) {
acc = (acc & 0xffff) + (acc >> 16);
}
return (u16_t)~(acc & 0xffff);
}
u16_t
inet_chksum_pbuf(struct pbuf *p)
{
u32_t acc;
struct pbuf *q;
u8_t swapped;
acc = 0;
swapped = 0;
for(q = p; q != NULL; q = q->next) {
acc += LWIP_CHKSUM(q->payload, q->len);
while (acc >> 16) {
acc = (acc & 0xffffUL) + (acc >> 16);
}
if (q->len % 2 != 0) {
swapped = 1 - swapped;
acc = (acc & 0x00ffUL << 8) | (acc & 0xff00UL >> 8);
}
}
if (swapped) {
acc = ((acc & 0x00ffUL) << 8) | ((acc & 0xff00UL) >> 8);
}
return (u16_t)~(acc & 0xffffUL);
}
/* Here for now until needed in other places in lwIP */
#ifndef isascii
#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up)
#define isascii(c) in_range(c, 0x20, 0x7f)
#define isdigit(c) in_range(c, '0', '9')
#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
#define islower(c) in_range(c, 'a', 'z')
#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
#endif
/*
* Ascii internet address interpretation routine.
* The value returned is in network order.
*/
/* */
/* inet_addr */
u32_t inet_addr(const char *cp)
{
struct in_addr val;
if (inet_aton(cp, &val)) {
return (val.s_addr);
}
return (INADDR_NONE);
}
/*
* Check whether "cp" is a valid ascii representation
* of an Internet address and convert to a binary address.
* Returns 1 if the address is valid, 0 if not.
* This replaces inet_addr, the return value from which
* cannot distinguish between failure and a local broadcast address.
*/
/* */
/* inet_aton */
s8_t
inet_aton(const char *cp, struct in_addr *addr)
{
u32_t val;
s32_t base, n;
char c;
u32_t parts[4];
u32_t* pp = parts;
c = *cp;
for (;;) {
/*
* Collect number up to ``.''.
* Values are specified as for C:
* 0x=hex, 0=octal, isdigit=decimal.
*/
if (!isdigit(c))
return (0);
val = 0; base = 10;
if (c == '0') {
c = *++cp;
if (c == 'x' || c == 'X')
base = 16, c = *++cp;
else
base = 8;
}
for (;;) {
if (isdigit(c)) {
val = (val * base) + (s16_t)(c - '0');
c = *++cp;
} else if (base == 16 && isxdigit(c)) {
val = (val << 4) |
(s16_t)(c + 10 - (islower(c) ? 'a' : 'A'));
c = *++cp;
} else
break;
}
if (c == '.') {
/*
* Internet format:
* a.b.c.d
* a.b.c (with c treated as 16 bits)
* a.b (with b treated as 24 bits)
*/
if (pp >= parts + 3)
return (0);
*pp++ = val;
c = *++cp;
} else
break;
}
/*
* Check for trailing characters.
*/
if (c != '\0' && (!isascii(c) || !isspace(c)))
return (0);
/*
* Concoct the address according to
* the number of parts specified.
*/
n = pp - parts + 1;
switch (n) {
case 0:
return (0); /* initial nondigit */
case 1: /* a -- 32 bits */
break;
case 2: /* a.b -- 8.24 bits */
if (val > 0xffffff)
return (0);
val |= parts[0] << 24;
break;
case 3: /* a.b.c -- 8.8.16 bits */
if (val > 0xffff)
return (0);
val |= (parts[0] << 24) | (parts[1] << 16);
break;
case 4: /* a.b.c.d -- 8.8.8.8 bits */
if (val > 0xff)
return (0);
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
break;
}
if (addr)
addr->s_addr = htonl(val);
return (1);
}
/* Convert numeric IP address into decimal dotted ASCII representation.
* returns ptr to static buffer; not reentrant!
*/
char *inet_ntoa(struct in_addr addr)
{
static char str[16];
u32_t s_addr = addr.s_addr;
char inv[3];
char *rp;
u8_t *ap;
u8_t rem;
u8_t n;
u8_t i;
rp = str;
ap = (u8_t *)&s_addr;
for(n = 0; n < 4; n++) {
i = 0;
do {
rem = *ap % (u8_t)10;
*ap /= (u8_t)10;
inv[i++] = '0' + rem;
} while(*ap);
while(i--)
*rp++ = inv[i];
*rp++ = '.';
ap++;
}
*--rp = 0;
return str;
}
#ifndef BYTE_ORDER
#error BYTE_ORDER is not defined
#endif
#if BYTE_ORDER == LITTLE_ENDIAN
u16_t
htons(u16_t n)
{
return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
}
u16_t
ntohs(u16_t n)
{
return htons(n);
}
u32_t
htonl(u32_t n)
{
return ((n & 0xff) << 24) |
((n & 0xff00) << 8) |
((n & 0xff0000) >> 8) |
((n & 0xff000000) >> 24);
}
u32_t
ntohl(u32_t n)
{
return htonl(n);
}
#endif /* BYTE_ORDER == LITTLE_ENDIAN */

View File

@@ -0,0 +1,168 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
/* inet6.c
*
* Functions common to all TCP/IP modules, such as the Internet checksum and the
* byte order functions.
*
*/
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/inet.h"
/* chksum:
*
* Sums up all 16 bit words in a memory portion. Also includes any odd byte.
* This function is used by the other checksum functions.
*
* For now, this is not optimized. Must be optimized for the particular processor
* arcitecture on which it is to run. Preferebly coded in assembler.
*/
static u32_t
chksum(void *dataptr, u16_t len)
{
u16_t *sdataptr = dataptr;
u32_t acc;
for(acc = 0; len > 1; len -= 2) {
acc += *sdataptr++;
}
/* add up any odd byte */
if (len == 1) {
acc += htons((u16_t)(*(u8_t *)dataptr) << 8);
}
return acc;
}
/* inet_chksum_pseudo:
*
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
*/
u16_t
inet_chksum_pseudo(struct pbuf *p,
struct ip_addr *src, struct ip_addr *dest,
u8_t proto, u32_t proto_len)
{
u32_t acc;
struct pbuf *q;
u8_t swapped, i;
acc = 0;
swapped = 0;
for(q = p; q != NULL; q = q->next) {
acc += chksum(q->payload, q->len);
while (acc >> 16) {
acc = (acc & 0xffff) + (acc >> 16);
}
if (q->len % 2 != 0) {
swapped = 1 - swapped;
acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8);
}
}
if (swapped) {
acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8);
}
for(i = 0; i < 8; i++) {
acc += ((u16_t *)src->addr)[i] & 0xffff;
acc += ((u16_t *)dest->addr)[i] & 0xffff;
while (acc >> 16) {
acc = (acc & 0xffff) + (acc >> 16);
}
}
acc += (u16_t)htons((u16_t)proto);
acc += ((u16_t *)&proto_len)[0] & 0xffff;
acc += ((u16_t *)&proto_len)[1] & 0xffff;
while (acc >> 16) {
acc = (acc & 0xffff) + (acc >> 16);
}
return ~(acc & 0xffff);
}
/* inet_chksum:
*
* Calculates the Internet checksum over a portion of memory. Used primarely for IP
* and ICMP.
*/
u16_t
inet_chksum(void *dataptr, u16_t len)
{
u32_t acc, sum;
acc = chksum(dataptr, len);
sum = (acc & 0xffff) + (acc >> 16);
sum += (sum >> 16);
return ~(sum & 0xffff);
}
u16_t
inet_chksum_pbuf(struct pbuf *p)
{
u32_t acc;
struct pbuf *q;
u8_t swapped;
acc = 0;
swapped = 0;
for(q = p; q != NULL; q = q->next) {
acc += chksum(q->payload, q->len);
while (acc >> 16) {
acc = (acc & 0xffff) + (acc >> 16);
}
if (q->len % 2 != 0) {
swapped = 1 - swapped;
acc = (acc & 0xff << 8) | (acc & 0xff00 >> 8);
}
}
if (swapped) {
acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8);
}
return ~(acc & 0xffff);
}

View File

@@ -0,0 +1,202 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
/* Some ICMP messages should be passed to the transport protocols. This
is not implemented. */
#include <string.h>
#include "lwip/opt.h"
#include "lwip/icmp.h"
#include "lwip/inet.h"
#include "lwip/ip.h"
#include "lwip/def.h"
#include "lwip/stats.h"
#include "lwip/snmp.h"
void
icmp_input(struct pbuf *p, struct netif *inp)
{
u8_t type;
u8_t code;
struct icmp_echo_hdr *iecho;
struct ip_hdr *iphdr;
struct ip_addr tmpaddr;
u16_t hlen;
ICMP_STATS_INC(icmp.recv);
snmp_inc_icmpinmsgs();
iphdr = p->payload;
hlen = IPH_HL(iphdr) * 4;
if (pbuf_header(p, -((s16_t)hlen)) || (p->tot_len < sizeof(u16_t)*2)) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len));
pbuf_free(p);
ICMP_STATS_INC(icmp.lenerr);
snmp_inc_icmpinerrors();
return;
}
type = *((u8_t *)p->payload);
code = *(((u8_t *)p->payload)+1);
switch (type) {
case ICMP_ECHO:
/* broadcast or multicast destination address? */
if (ip_addr_isbroadcast(&iphdr->dest, inp) || ip_addr_ismulticast(&iphdr->dest)) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast or broadcast pings\n"));
ICMP_STATS_INC(icmp.err);
pbuf_free(p);
return;
}
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n"));
if (p->tot_len < sizeof(struct icmp_echo_hdr)) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
pbuf_free(p);
ICMP_STATS_INC(icmp.lenerr);
snmp_inc_icmpinerrors();
return;
}
iecho = p->payload;
if (inet_chksum_pbuf(p) != 0) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n"));
pbuf_free(p);
ICMP_STATS_INC(icmp.chkerr);
snmp_inc_icmpinerrors();
return;
}
tmpaddr.addr = iphdr->src.addr;
iphdr->src.addr = iphdr->dest.addr;
iphdr->dest.addr = tmpaddr.addr;
ICMPH_TYPE_SET(iecho, ICMP_ER);
/* adjust the checksum */
if (iecho->chksum >= htons(0xffff - (ICMP_ECHO << 8))) {
iecho->chksum += htons(ICMP_ECHO << 8) + 1;
} else {
iecho->chksum += htons(ICMP_ECHO << 8);
}
ICMP_STATS_INC(icmp.xmit);
/* increase number of messages attempted to send */
snmp_inc_icmpoutmsgs();
/* increase number of echo replies attempted to send */
snmp_inc_icmpoutechoreps();
pbuf_header(p, hlen);
ip_output_if(p, &(iphdr->src), IP_HDRINCL,
IPH_TTL(iphdr), 0, IP_PROTO_ICMP, inp);
break;
default:
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n", (s16_t)type, (s16_t)code));
ICMP_STATS_INC(icmp.proterr);
ICMP_STATS_INC(icmp.drop);
}
pbuf_free(p);
}
void
icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
{
struct pbuf *q;
struct ip_hdr *iphdr;
struct icmp_dur_hdr *idur;
q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
/* ICMP header + IP header + 8 bytes of data */
iphdr = p->payload;
idur = q->payload;
ICMPH_TYPE_SET(idur, ICMP_DUR);
ICMPH_CODE_SET(idur, t);
memcpy((u8_t *)q->payload + 8, p->payload, IP_HLEN + 8);
/* calculate checksum */
idur->chksum = 0;
idur->chksum = inet_chksum(idur, q->len);
ICMP_STATS_INC(icmp.xmit);
/* increase number of messages attempted to send */
snmp_inc_icmpoutmsgs();
/* increase number of destination unreachable messages attempted to send */
snmp_inc_icmpoutdestunreachs();
ip_output(q, NULL, &(iphdr->src),
ICMP_TTL, 0, IP_PROTO_ICMP);
pbuf_free(q);
}
#if IP_FORWARD
void
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
{
struct pbuf *q;
struct ip_hdr *iphdr;
struct icmp_te_hdr *tehdr;
q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
iphdr = p->payload;
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src));
LWIP_DEBUGF(ICMP_DEBUG, (" to "));
ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest));
LWIP_DEBUGF(ICMP_DEBUG, ("\n"));
tehdr = q->payload;
ICMPH_TYPE_SET(tehdr, ICMP_TE);
ICMPH_CODE_SET(tehdr, t);
/* copy fields from original packet */
memcpy((u8_t *)q->payload + 8, (u8_t *)p->payload, IP_HLEN + 8);
/* calculate checksum */
tehdr->chksum = 0;
tehdr->chksum = inet_chksum(tehdr, q->len);
ICMP_STATS_INC(icmp.xmit);
/* increase number of messages attempted to send */
snmp_inc_icmpoutmsgs();
/* increase number of destination unreachable messages attempted to send */
snmp_inc_icmpouttimeexcds();
ip_output(q, NULL, &(iphdr->src),
ICMP_TTL, 0, IP_PROTO_ICMP);
pbuf_free(q);
}
#endif /* IP_FORWARD */

View File

@@ -0,0 +1,508 @@
/* @file
*
* This is the IP layer implementation for incoming and outgoing IP traffic.
*
* @see ip_frag.c
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/ip.h"
#include "lwip/ip_frag.h"
#include "lwip/inet.h"
#include "lwip/netif.h"
#include "lwip/icmp.h"
#include "lwip/raw.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
#include "lwip/stats.h"
#include "arch/perf.h"
#include "lwip/snmp.h"
#if LWIP_DHCP
# include "lwip/dhcp.h"
#endif /* LWIP_DHCP */
/**
* Initializes the IP layer.
*/
void
ip_init(void)
{
/* no initializations as of yet */
}
/**
* Finds the appropriate network interface for a given IP address. It
* searches the list of network interfaces linearly. A match is found
* if the masked IP address of the network interface equals the masked
* IP address given to the function.
*/
struct netif *
ip_route(struct ip_addr *dest)
{
struct netif *netif;
/* iterate through netifs */
for(netif = netif_list; netif != NULL; netif = netif->next) {
/* network mask matches? */
if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
/* return netif on which to forward IP packet */
return netif;
}
}
/* no matching netif found, use default netif */
return netif_default;
}
#if IP_FORWARD
/**
* Forwards an IP packet. It finds an appropriate route for the
* packet, decrements the TTL value of the packet, adjusts the
* checksum and outputs the packet on the appropriate interface.
*/
static struct netif *
ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
{
struct netif *netif;
PERF_START;
/* Find network interface where to forward this IP packet to. */
netif = ip_route((struct ip_addr *)&(iphdr->dest));
if (netif == NULL) {
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%"X32_F" found\n",
iphdr->dest.addr));
snmp_inc_ipnoroutes();
return (struct netif *)NULL;
}
/* Do not forward packets onto the same network interface on which
* they arrived. */
if (netif == inp) {
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n"));
snmp_inc_ipnoroutes();
return (struct netif *)NULL;
}
/* decrement TTL */
IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1);
/* send ICMP if TTL == 0 */
if (IPH_TTL(iphdr) == 0) {
/* Don't send ICMP messages in response to ICMP messages */
if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) {
icmp_time_exceeded(p, ICMP_TE_TTL);
snmp_inc_icmpouttimeexcds();
}
return (struct netif *)NULL;
}
/* Incrementally update the IP checksum. */
if (IPH_CHKSUM(iphdr) >= htons(0xffff - 0x100)) {
IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100) + 1);
} else {
IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100));
}
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%"X32_F"\n",
iphdr->dest.addr));
IP_STATS_INC(ip.fw);
IP_STATS_INC(ip.xmit);
snmp_inc_ipforwdatagrams();
PERF_STOP("ip_forward");
/* transmit pbuf on chosen interface */
netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
return netif;
}
#endif /* IP_FORWARD */
/**
* This function is called by the network interface device driver when
* an IP packet is received. The function does the basic checks of the
* IP header such as packet size being at least larger than the header
* size etc. If the packet was not destined for us, the packet is
* forwarded (using ip_forward). The IP checksum is always checked.
*
* Finally, the packet is sent to the upper layer protocol input function.
*
*
*
*/
err_t
ip_input(struct pbuf *p, struct netif *inp) {
struct ip_hdr *iphdr;
struct netif *netif;
u16_t iphdrlen;
IP_STATS_INC(ip.recv);
snmp_inc_ipinreceives();
/* identify the IP header */
iphdr = p->payload;
if (IPH_V(iphdr) != 4) {
LWIP_DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr)));
ip_debug_print(p);
pbuf_free(p);
IP_STATS_INC(ip.err);
IP_STATS_INC(ip.drop);
snmp_inc_ipunknownprotos();
return ERR_OK;
}
/* obtain IP header length in number of 32-bit words */
iphdrlen = IPH_HL(iphdr);
/* calculate IP header length in bytes */
iphdrlen *= 4;
/* header length exceeds first pbuf length? */
if (iphdrlen > p->len) {
LWIP_DEBUGF(IP_DEBUG | 2, ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet droppped.\n",
iphdrlen, p->len));
/* free (drop) packet pbufs */
pbuf_free(p);
IP_STATS_INC(ip.lenerr);
IP_STATS_INC(ip.drop);
snmp_inc_ipindiscards();
return ERR_OK;
}
/* verify checksum */
#if CHECKSUM_CHECK_IP
if (inet_chksum(iphdr, iphdrlen) != 0) {
LWIP_DEBUGF(IP_DEBUG | 2, ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdrlen)));
ip_debug_print(p);
pbuf_free(p);
IP_STATS_INC(ip.chkerr);
IP_STATS_INC(ip.drop);
snmp_inc_ipindiscards();
return ERR_OK;
}
#endif
/* Trim pbuf. This should have been done at the netif layer,
* but we'll do it anyway just to be sure that its done. */
pbuf_realloc(p, ntohs(IPH_LEN(iphdr)));
/* match packet against an interface, i.e. is this packet for us? */
for (netif = netif_list; netif != NULL; netif = netif->next) {
LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n",
iphdr->dest.addr, netif->ip_addr.addr,
iphdr->dest.addr & netif->netmask.addr,
netif->ip_addr.addr & netif->netmask.addr,
iphdr->dest.addr & ~(netif->netmask.addr)));
/* interface is up and configured? */
if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr))))
{
/* unicast to this interface address? */
if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
/* or broadcast on this interface network address? */
ip_addr_isbroadcast(&(iphdr->dest), netif)) {
LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
netif->name[0], netif->name[1]));
/* break out of for loop */
break;
}
}
}
#if LWIP_DHCP
/* Pass DHCP messages regardless of destination address. DHCP traffic is addressed
* using link layer addressing (such as Ethernet MAC) so we must not filter on IP.
* According to RFC 1542 section 3.1.1, referred by RFC 2131).
*/
if (netif == NULL) {
/* remote port is DHCP server? */
if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: UDP packet to DHCP client port %"U16_F"\n",
ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest)));
if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest) == DHCP_CLIENT_PORT) {
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: DHCP packet accepted.\n"));
netif = inp;
}
}
}
#endif /* LWIP_DHCP */
/* packet not for us? */
if (netif == NULL) {
/* packet not for us, route or discard */
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: packet not for us.\n"));
#if IP_FORWARD
/* non-broadcast packet? */
if (!ip_addr_isbroadcast(&(iphdr->dest), inp)) {
/* try to forward IP packet on (other) interfaces */
ip_forward(p, iphdr, inp);
}
else
#endif /* IP_FORWARD */
{
snmp_inc_ipindiscards();
}
pbuf_free(p);
return ERR_OK;
}
/* packet consists of multiple fragments? */
if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
#if IP_REASSEMBLY /* packet fragment reassembly code present? */
LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip_reass()\n",
ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & htons(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8));
/* reassemble the packet*/
p = ip_reass(p);
/* packet not fully reassembled yet? */
if (p == NULL) {
return ERR_OK;
}
iphdr = p->payload;
#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
pbuf_free(p);
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n",
ntohs(IPH_OFFSET(iphdr))));
IP_STATS_INC(ip.opterr);
IP_STATS_INC(ip.drop);
snmp_inc_ipunknownprotos();
return ERR_OK;
#endif /* IP_REASSEMBLY */
}
#if IP_OPTIONS == 0 /* no support for IP options in the IP header? */
if (iphdrlen > IP_HLEN) {
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since there were IP options (while IP_OPTIONS == 0).\n"));
pbuf_free(p);
IP_STATS_INC(ip.opterr);
IP_STATS_INC(ip.drop);
snmp_inc_ipunknownprotos();
return ERR_OK;
}
#endif /* IP_OPTIONS == 0 */
/* send to upper layers */
LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n"));
ip_debug_print(p);
LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
#if LWIP_RAW
/* raw input did not eat the packet? */
if (raw_input(p, inp) == 0) {
#endif /* LWIP_RAW */
switch (IPH_PROTO(iphdr)) {
#if LWIP_UDP
case IP_PROTO_UDP:
case IP_PROTO_UDPLITE:
snmp_inc_ipindelivers();
udp_input(p, inp);
break;
#endif /* LWIP_UDP */
#if LWIP_TCP
case IP_PROTO_TCP:
snmp_inc_ipindelivers();
tcp_input(p, inp);
break;
#endif /* LWIP_TCP */
case IP_PROTO_ICMP:
snmp_inc_ipindelivers();
icmp_input(p, inp);
break;
default:
/* send ICMP destination protocol unreachable unless is was a broadcast */
if (!ip_addr_isbroadcast(&(iphdr->dest), inp) &&
!ip_addr_ismulticast(&(iphdr->dest))) {
p->payload = iphdr;
icmp_dest_unreach(p, ICMP_DUR_PROTO);
}
pbuf_free(p);
LWIP_DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr)));
IP_STATS_INC(ip.proterr);
IP_STATS_INC(ip.drop);
snmp_inc_ipunknownprotos();
}
#if LWIP_RAW
} /* LWIP_RAW */
#endif
return ERR_OK;
}
/**
* Sends an IP packet on a network interface. This function constructs
* the IP header and calculates the IP header checksum. If the source
* IP address is NULL, the IP address of the outgoing network
* interface is filled in as source address.
*/
err_t
ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t tos,
u8_t proto, struct netif *netif)
{
struct ip_hdr *iphdr;
u16_t ip_id = 0;
snmp_inc_ipoutrequests();
if (dest != IP_HDRINCL) {
if (pbuf_header(p, IP_HLEN)) {
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: not enough room for IP header in pbuf\n"));
IP_STATS_INC(ip.err);
snmp_inc_ipoutdiscards();
return ERR_BUF;
}
iphdr = p->payload;
IPH_TTL_SET(iphdr, ttl);
IPH_PROTO_SET(iphdr, proto);
ip_addr_set(&(iphdr->dest), dest);
IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, tos);
IPH_LEN_SET(iphdr, htons(p->tot_len));
IPH_OFFSET_SET(iphdr, htons(IP_DF));
IPH_ID_SET(iphdr, htons(ip_id));
++ip_id;
if (ip_addr_isany(src)) {
ip_addr_set(&(iphdr->src), &(netif->ip_addr));
} else {
ip_addr_set(&(iphdr->src), src);
}
IPH_CHKSUM_SET(iphdr, 0);
#if CHECKSUM_GEN_IP
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
#endif
} else {
iphdr = p->payload;
dest = &(iphdr->dest);
}
#if IP_FRAG
/* don't fragment if interface has mtu set to 0 [loopif] */
if (netif->mtu && (p->tot_len > netif->mtu))
return ip_frag(p,netif,dest);
#endif
IP_STATS_INC(ip.xmit);
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num));
ip_debug_print(p);
LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
return netif->output(netif, p, dest);
}
/**
* Simple interface to ip_output_if. It finds the outgoing network
* interface and calls upon ip_output_if to do the actual work.
*/
err_t
ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t tos, u8_t proto)
{
struct netif *netif;
if ((netif = ip_route(dest)) == NULL) {
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: No route to 0x%"X32_F"\n", dest->addr));
IP_STATS_INC(ip.rterr);
snmp_inc_ipoutdiscards();
return ERR_RTE;
}
return ip_output_if(p, src, dest, ttl, tos, proto, netif);
}
#if IP_DEBUG
void
ip_debug_print(struct pbuf *p)
{
struct ip_hdr *iphdr = p->payload;
u8_t *payload;
payload = (u8_t *)iphdr + IP_HLEN;
LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n",
IPH_V(iphdr),
IPH_HL(iphdr),
IPH_TOS(iphdr),
ntohs(IPH_LEN(iphdr))));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n",
ntohs(IPH_ID(iphdr)),
ntohs(IPH_OFFSET(iphdr)) >> 15 & 1,
ntohs(IPH_OFFSET(iphdr)) >> 14 & 1,
ntohs(IPH_OFFSET(iphdr)) >> 13 & 1,
ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n",
IPH_TTL(iphdr),
IPH_PROTO(iphdr),
ntohs(IPH_CHKSUM(iphdr))));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n",
ip4_addr1(&iphdr->src),
ip4_addr2(&iphdr->src),
ip4_addr3(&iphdr->src),
ip4_addr4(&iphdr->src)));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n",
ip4_addr1(&iphdr->dest),
ip4_addr2(&iphdr->dest),
ip4_addr3(&iphdr->dest),
ip4_addr4(&iphdr->dest)));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
}
#endif /* IP_DEBUG */

View File

@@ -0,0 +1,72 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/ip_addr.h"
#include "lwip/inet.h"
#include "lwip/netif.h"
/* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */
const struct ip_addr ip_addr_any = { 0x00000000UL };
const struct ip_addr ip_addr_broadcast = { 0xffffffffUL };
/* Determine if an address is a broadcast address on a network interface
*
* @param addr address to be checked
* @param netif the network interface against which the address is checked
* @return returns non-zero if the address is a broadcast address
*
*/
u8_t ip_addr_isbroadcast(struct ip_addr *addr, struct netif *netif)
{
/* all ones (broadcast) or all zeroes (old skool broadcast) */
if ((addr->addr == ip_addr_broadcast.addr) ||
(addr->addr == ip_addr_any.addr))
return 1;
/* no broadcast support on this network interface? */
else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0)
/* the given address cannot be a broadcast address
* nor can we check against any broadcast addresses */
return 0;
/* address matches network interface address exactly? => no broadcast */
else if (addr->addr == netif->ip_addr.addr)
return 0;
/* on the same (sub) network... */
else if (ip_addr_netcmp(addr, &(netif->ip_addr), &(netif->netmask))
/* ...and host identifier bits are all ones? =>... */
&& ((addr->addr & ~netif->netmask.addr) ==
(ip_addr_broadcast.addr & ~netif->netmask.addr)))
/* => network broadcast address */
return 1;
else
return 0;
}

View File

@@ -0,0 +1,366 @@
/* @file
*
* This is the IP packet segmentation and reassembly implementation.
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Jani Monoses <jani@iv.ro>
* original reassembly code by Adam Dunkels <adam@sics.se>
*
*/
#include <string.h>
#include "lwip/opt.h"
/* #include "lwip/sys.h" */
#include "lwip/ip.h"
#include "lwip/ip_frag.h"
#include "lwip/netif.h"
#include "lwip/stats.h"
/*
* Copy len bytes from offset in pbuf to buffer
*
* helper used by both ip_reass and ip_frag
*/
static struct pbuf *
copy_from_pbuf(struct pbuf *p, u16_t * offset,
u8_t * buffer, u16_t len)
{
u16_t l;
p->payload = (u8_t *)p->payload + *offset;
p->len -= *offset;
while (len) {
l = len < p->len ? len : p->len;
memcpy(buffer, p->payload, l);
buffer += l;
len -= l;
if (len)
p = p->next;
else
*offset = l;
}
return p;
}
#define IP_REASS_BUFSIZE 5760
#define IP_REASS_MAXAGE 30
#define IP_REASS_TMO 1000
static u8_t ip_reassbuf[IP_HLEN + IP_REASS_BUFSIZE];
static u8_t ip_reassbitmap[IP_REASS_BUFSIZE / (8 * 8) + 1];
static const u8_t bitmap_bits[8] = { 0xff, 0x7f, 0x3f, 0x1f,
0x0f, 0x07, 0x03, 0x01
};
static u16_t ip_reasslen;
static u8_t ip_reassflags;
#define IP_REASS_FLAG_LASTFRAG 0x01
static u8_t ip_reasstmr;
/**
* Reassembly timer base function
* for both NO_SYS == 0 and 1 (!).
*
* Should be called every 1000 msec.
*/
void
ip_reass_tmr(void)
{
if (ip_reasstmr > 0) {
ip_reasstmr--;
}
}
/**
* Reassembles incoming IP fragments into an IP datagram.
*
* @param p points to a pbuf chain of the fragment
* @return NULL if reassembly is incomplete, ? otherwise
*/
struct pbuf *
ip_reass(struct pbuf *p)
{
struct pbuf *q;
struct ip_hdr *fraghdr, *iphdr;
u16_t offset, len;
u16_t i;
IPFRAG_STATS_INC(ip_frag.recv);
iphdr = (struct ip_hdr *) ip_reassbuf;
fraghdr = (struct ip_hdr *) p->payload;
/* If ip_reasstmr is zero, no packet is present in the buffer, so we
write the IP header of the fragment into the reassembly
buffer. The timer is updated with the maximum age. */
if (ip_reasstmr == 0) {
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: new packet\n"));
memcpy(iphdr, fraghdr, IP_HLEN);
ip_reasstmr = IP_REASS_MAXAGE;
ip_reassflags = 0;
/* Clear the bitmap. */
memset(ip_reassbitmap, 0, sizeof(ip_reassbitmap));
}
/* Check if the incoming fragment matches the one currently present
in the reasembly buffer. If so, we proceed with copying the
fragment into the buffer. */
if (ip_addr_cmp(&iphdr->src, &fraghdr->src) &&
ip_addr_cmp(&iphdr->dest, &fraghdr->dest) &&
IPH_ID(iphdr) == IPH_ID(fraghdr)) {
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching previous fragment ID=%"X16_F"\n",
ntohs(IPH_ID(fraghdr))));
IPFRAG_STATS_INC(ip_frag.cachehit);
/* Find out the offset in the reassembly buffer where we should
copy the fragment. */
len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4;
offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8;
/* If the offset or the offset + fragment length overflows the
reassembly buffer, we discard the entire packet. */
if (offset > IP_REASS_BUFSIZE || offset + len > IP_REASS_BUFSIZE) {
LWIP_DEBUGF(IP_REASS_DEBUG,
("ip_reass: fragment outside of buffer (%"S16_F":%"S16_F"/%"S16_F").\n", offset,
offset + len, IP_REASS_BUFSIZE));
ip_reasstmr = 0;
goto nullreturn;
}
/* Copy the fragment into the reassembly buffer, at the right
offset. */
LWIP_DEBUGF(IP_REASS_DEBUG,
("ip_reass: copying with offset %"S16_F" into %"S16_F":%"S16_F"\n", offset,
IP_HLEN + offset, IP_HLEN + offset + len));
i = IPH_HL(fraghdr) * 4;
copy_from_pbuf(p, &i, &ip_reassbuf[IP_HLEN + offset], len);
/* Update the bitmap. */
if (offset / (8 * 8) == (offset + len) / (8 * 8)) {
LWIP_DEBUGF(IP_REASS_DEBUG,
("ip_reass: updating single byte in bitmap.\n"));
/* If the two endpoints are in the same byte, we only update that byte. */
LWIP_ASSERT("offset / (8 * 8) < sizeof(ip_reassbitmap)",
offset / (8 * 8) < sizeof(ip_reassbitmap));
ip_reassbitmap[offset / (8 * 8)] |=
bitmap_bits[(offset / 8) & 7] &
~bitmap_bits[((offset + len) / 8) & 7];
} else {
/* If the two endpoints are in different bytes, we update the
bytes in the endpoints and fill the stuff inbetween with
0xff. */
LWIP_ASSERT("offset / (8 * 8) < sizeof(ip_reassbitmap)",
offset / (8 * 8) < sizeof(ip_reassbitmap));
ip_reassbitmap[offset / (8 * 8)] |= bitmap_bits[(offset / 8) & 7];
LWIP_DEBUGF(IP_REASS_DEBUG,
("ip_reass: updating many bytes in bitmap (%"S16_F":%"S16_F").\n",
1 + offset / (8 * 8), (offset + len) / (8 * 8)));
for (i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {
ip_reassbitmap[i] = 0xff;
}
LWIP_ASSERT("(offset + len) / (8 * 8) < sizeof(ip_reassbitmap)",
(offset + len) / (8 * 8) < sizeof(ip_reassbitmap));
ip_reassbitmap[(offset + len) / (8 * 8)] |=
~bitmap_bits[((offset + len) / 8) & 7];
}
/* If this fragment has the More Fragments flag set to zero, we
know that this is the last fragment, so we can calculate the
size of the entire packet. We also set the
IP_REASS_FLAG_LASTFRAG flag to indicate that we have received
the final fragment. */
if ((ntohs(IPH_OFFSET(fraghdr)) & IP_MF) == 0) {
ip_reassflags |= IP_REASS_FLAG_LASTFRAG;
ip_reasslen = offset + len;
LWIP_DEBUGF(IP_REASS_DEBUG,
("ip_reass: last fragment seen, total len %"S16_F"\n",
ip_reasslen));
}
/* Finally, we check if we have a full packet in the buffer. We do
this by checking if we have the last fragment and if all bits
in the bitmap are set. */
if (ip_reassflags & IP_REASS_FLAG_LASTFRAG) {
/* Check all bytes up to and including all but the last byte in
the bitmap. */
LWIP_ASSERT("ip_reasslen / (8 * 8) - 1 < sizeof(ip_reassbitmap)",
ip_reasslen / (8 * 8) - 1 < sizeof(ip_reassbitmap));
for (i = 0; i < ip_reasslen / (8 * 8) - 1; ++i) {
if (ip_reassbitmap[i] != 0xff) {
LWIP_DEBUGF(IP_REASS_DEBUG,
("ip_reass: last fragment seen, bitmap %"S16_F"/%"S16_F" failed (%"X16_F")\n",
i, ip_reasslen / (8 * 8) - 1, ip_reassbitmap[i]));
goto nullreturn;
}
}
/* Check the last byte in the bitmap. It should contain just the
right amount of bits. */
LWIP_ASSERT("ip_reasslen / (8 * 8) < sizeof(ip_reassbitmap)",
ip_reasslen / (8 * 8) < sizeof(ip_reassbitmap));
if (ip_reassbitmap[ip_reasslen / (8 * 8)] !=
(u8_t) ~ bitmap_bits[ip_reasslen / 8 & 7]) {
LWIP_DEBUGF(IP_REASS_DEBUG,
("ip_reass: last fragment seen, bitmap %"S16_F" didn't contain %"X16_F" (%"X16_F")\n",
ip_reasslen / (8 * 8), ~bitmap_bits[ip_reasslen / 8 & 7],
ip_reassbitmap[ip_reasslen / (8 * 8)]));
goto nullreturn;
}
/* Pretend to be a "normal" (i.e., not fragmented) IP packet
from now on. */
ip_reasslen += IP_HLEN;
IPH_LEN_SET(iphdr, htons(ip_reasslen));
IPH_OFFSET_SET(iphdr, 0);
IPH_CHKSUM_SET(iphdr, 0);
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
/* If we have come this far, we have a full packet in the
buffer, so we allocate a pbuf and copy the packet into it. We
also reset the timer. */
ip_reasstmr = 0;
pbuf_free(p);
p = pbuf_alloc(PBUF_LINK, ip_reasslen, PBUF_POOL);
if (p != NULL) {
i = 0;
for (q = p; q != NULL; q = q->next) {
/* Copy enough bytes to fill this pbuf in the chain. The
available data in the pbuf is given by the q->len variable. */
LWIP_DEBUGF(IP_REASS_DEBUG,
("ip_reass: memcpy from %p (%"S16_F") to %p, %"S16_F" bytes\n",
(void *)&ip_reassbuf[i], i, q->payload,
q->len > ip_reasslen - i ? ip_reasslen - i : q->len));
memcpy(q->payload, &ip_reassbuf[i],
q->len > ip_reasslen - i ? ip_reasslen - i : q->len);
i += q->len;
}
IPFRAG_STATS_INC(ip_frag.fw);
} else {
IPFRAG_STATS_INC(ip_frag.memerr);
}
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: p %p\n", (void*)p));
return p;
}
}
nullreturn:
IPFRAG_STATS_INC(ip_frag.drop);
pbuf_free(p);
return NULL;
}
#define MAX_MTU 1500
static u8_t buf[MEM_ALIGN_SIZE(MAX_MTU)];
/**
* Fragment an IP datagram if too large for the netif.
*
* Chop the datagram in MTU sized chunks and send them in order
* by using a fixed size static memory buffer (PBUF_ROM)
*/
err_t
ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
{
struct pbuf *rambuf;
struct pbuf *header;
struct ip_hdr *iphdr;
u16_t nfb = 0;
u16_t left, cop;
u16_t mtu = netif->mtu;
u16_t ofo, omf;
u16_t last;
u16_t poff = IP_HLEN;
u16_t tmp;
/* Get a RAM based MTU sized pbuf */
rambuf = pbuf_alloc(PBUF_LINK, 0, PBUF_REF);
if (rambuf == NULL) {
return ERR_MEM;
}
rambuf->tot_len = rambuf->len = mtu;
rambuf->payload = MEM_ALIGN((void *)buf);
/* Copy the IP header in it */
iphdr = rambuf->payload;
memcpy(iphdr, p->payload, IP_HLEN);
/* Save original offset */
tmp = ntohs(IPH_OFFSET(iphdr));
ofo = tmp & IP_OFFMASK;
omf = tmp & IP_MF;
left = p->tot_len - IP_HLEN;
while (left) {
last = (left <= mtu - IP_HLEN);
/* Set new offset and MF flag */
ofo += nfb;
tmp = omf | (IP_OFFMASK & (ofo));
if (!last)
tmp = tmp | IP_MF;
IPH_OFFSET_SET(iphdr, htons(tmp));
/* Fill this fragment */
nfb = (mtu - IP_HLEN) / 8;
cop = last ? left : nfb * 8;
p = copy_from_pbuf(p, &poff, (u8_t *) iphdr + IP_HLEN, cop);
/* Correct header */
IPH_LEN_SET(iphdr, htons(cop + IP_HLEN));
IPH_CHKSUM_SET(iphdr, 0);
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
if (last)
pbuf_realloc(rambuf, left + IP_HLEN);
/* This part is ugly: we alloc a RAM based pbuf for
* the link level header for each chunk and then
* free it.A PBUF_ROM style pbuf for which pbuf_header
* worked would make things simpler.
*/
header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM);
if (header != NULL) {
pbuf_chain(header, rambuf);
netif->output(netif, header, dest);
IPFRAG_STATS_INC(ip_frag.xmit);
pbuf_free(header);
} else {
pbuf_free(rambuf);
return ERR_MEM;
}
left -= cop;
}
pbuf_free(rambuf);
return ERR_OK;
}

View File

@@ -0,0 +1 @@
IPv6 support in lwIP is very experimental.

View File

@@ -0,0 +1,184 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
/* Some ICMP messages should be passed to the transport protocols. This
is not implemented. */
#include "lwip/opt.h"
#include "lwip/icmp.h"
#include "lwip/inet.h"
#include "lwip/ip.h"
#include "lwip/def.h"
#include "lwip/stats.h"
void
icmp_input(struct pbuf *p, struct netif *inp)
{
u8_t type;
struct icmp_echo_hdr *iecho;
struct ip_hdr *iphdr;
struct ip_addr tmpaddr;
#ifdef ICMP_STATS
++lwip_stats.icmp.recv;
#endif /* ICMP_STATS */
/* TODO: check length before accessing payload! */
type = ((u8_t *)p->payload)[0];
switch (type) {
case ICMP6_ECHO:
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n"));
if (p->tot_len < sizeof(struct icmp_echo_hdr)) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
pbuf_free(p);
#ifdef ICMP_STATS
++lwip_stats.icmp.lenerr;
#endif /* ICMP_STATS */
return;
}
iecho = p->payload;
iphdr = (struct ip_hdr *)((u8_t *)p->payload - IP_HLEN);
if (inet_chksum_pbuf(p) != 0) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%"X16_F")\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
#ifdef ICMP_STATS
++lwip_stats.icmp.chkerr;
#endif /* ICMP_STATS */
/* return;*/
}
LWIP_DEBUGF(ICMP_DEBUG, ("icmp: p->len %"S16_F" p->tot_len %"S16_F"\n", p->len, p->tot_len));
ip_addr_set(&tmpaddr, &(iphdr->src));
ip_addr_set(&(iphdr->src), &(iphdr->dest));
ip_addr_set(&(iphdr->dest), &tmpaddr);
iecho->type = ICMP6_ER;
/* adjust the checksum */
if (iecho->chksum >= htons(0xffff - (ICMP6_ECHO << 8))) {
iecho->chksum += htons(ICMP6_ECHO << 8) + 1;
} else {
iecho->chksum += htons(ICMP6_ECHO << 8);
}
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%"X16_F")\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
#ifdef ICMP_STATS
++lwip_stats.icmp.xmit;
#endif /* ICMP_STATS */
/* LWIP_DEBUGF("icmp: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len);*/
ip_output_if (p, &(iphdr->src), IP_HDRINCL,
iphdr->hoplim, IP_PROTO_ICMP, inp);
break;
default:
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" not supported.\n", (s16_t)type));
#ifdef ICMP_STATS
++lwip_stats.icmp.proterr;
++lwip_stats.icmp.drop;
#endif /* ICMP_STATS */
}
pbuf_free(p);
}
void
icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
{
struct pbuf *q;
struct ip_hdr *iphdr;
struct icmp_dur_hdr *idur;
q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
/* ICMP header + IP header + 8 bytes of data */
iphdr = p->payload;
idur = q->payload;
idur->type = (u8_t)ICMP6_DUR;
idur->icode = (u8_t)t;
memcpy((u8_t *)q->payload + 8, p->payload, IP_HLEN + 8);
/* calculate checksum */
idur->chksum = 0;
idur->chksum = inet_chksum(idur, q->len);
#ifdef ICMP_STATS
++lwip_stats.icmp.xmit;
#endif /* ICMP_STATS */
ip_output(q, NULL,
(struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP);
pbuf_free(q);
}
void
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
{
struct pbuf *q;
struct ip_hdr *iphdr;
struct icmp_te_hdr *tehdr;
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded\n"));
q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
iphdr = p->payload;
tehdr = q->payload;
tehdr->type = (u8_t)ICMP6_TE;
tehdr->icode = (u8_t)t;
/* copy fields from original packet */
memcpy((u8_t *)q->payload + 8, (u8_t *)p->payload, IP_HLEN + 8);
/* calculate checksum */
tehdr->chksum = 0;
tehdr->chksum = inet_chksum(tehdr, q->len);
#ifdef ICMP_STATS
++lwip_stats.icmp.xmit;
#endif /* ICMP_STATS */
ip_output(q, NULL,
(struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP);
pbuf_free(q);
}

View File

@@ -0,0 +1,386 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
/* ip.c
*
* This is the code for the IP layer for IPv6.
*
*/
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/ip.h"
#include "lwip/inet.h"
#include "lwip/netif.h"
#include "lwip/icmp.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
#include "lwip/stats.h"
#include "arch/perf.h"
/* ip_init:
*
* Initializes the IP layer.
*/
void
ip_init(void)
{
}
/* ip_route:
*
* Finds the appropriate network interface for a given IP address. It searches the
* list of network interfaces linearly. A match is found if the masked IP address of
* the network interface equals the masked IP address given to the function.
*/
struct netif *
ip_route(struct ip_addr *dest)
{
struct netif *netif;
for(netif = netif_list; netif != NULL; netif = netif->next) {
if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
return netif;
}
}
return netif_default;
}
/* ip_forward:
*
* Forwards an IP packet. It finds an appropriate route for the packet, decrements
* the TTL value of the packet, adjusts the checksum and outputs the packet on the
* appropriate interface.
*/
static void
ip_forward(struct pbuf *p, struct ip_hdr *iphdr)
{
struct netif *netif;
PERF_START;
if ((netif = ip_route((struct ip_addr *)&(iphdr->dest))) == NULL) {
LWIP_DEBUGF(IP_DEBUG, ("ip_input: no forwarding route found for "));
#if IP_DEBUG
ip_addr_debug_print(IP_DEBUG, &(iphdr->dest));
#endif /* IP_DEBUG */
LWIP_DEBUGF(IP_DEBUG, ("\n"));
pbuf_free(p);
return;
}
/* Decrement TTL and send ICMP if ttl == 0. */
if (--iphdr->hoplim == 0) {
/* Don't send ICMP messages in response to ICMP messages */
if (iphdr->nexthdr != IP_PROTO_ICMP) {
icmp_time_exceeded(p, ICMP_TE_TTL);
}
pbuf_free(p);
return;
}
/* Incremental update of the IP checksum. */
/* if (iphdr->chksum >= htons(0xffff - 0x100)) {
iphdr->chksum += htons(0x100) + 1;
} else {
iphdr->chksum += htons(0x100);
}*/
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to "));
#if IP_DEBUG
ip_addr_debug_print(IP_DEBUG, &(iphdr->dest));
#endif /* IP_DEBUG */
LWIP_DEBUGF(IP_DEBUG, ("\n"));
#ifdef IP_STATS
++lwip_stats.ip.fw;
++lwip_stats.ip.xmit;
#endif /* IP_STATS */
PERF_STOP("ip_forward");
netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
}
/* ip_input:
*
* This function is called by the network interface device driver when an IP packet is
* received. The function does the basic checks of the IP header such as packet size
* being at least larger than the header size etc. If the packet was not destined for
* us, the packet is forwarded (using ip_forward). The IP checksum is always checked.
*
* Finally, the packet is sent to the upper layer protocol input function.
*/
void
ip_input(struct pbuf *p, struct netif *inp) {
struct ip_hdr *iphdr;
struct netif *netif;
PERF_START;
#if IP_DEBUG
ip_debug_print(p);
#endif /* IP_DEBUG */
#ifdef IP_STATS
++lwip_stats.ip.recv;
#endif /* IP_STATS */
/* identify the IP header */
iphdr = p->payload;
if (iphdr->v != 6) {
LWIP_DEBUGF(IP_DEBUG, ("IP packet dropped due to bad version number\n"));
#if IP_DEBUG
ip_debug_print(p);
#endif /* IP_DEBUG */
pbuf_free(p);
#ifdef IP_STATS
++lwip_stats.ip.err;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
return;
}
/* is this packet for us? */
for(netif = netif_list; netif != NULL; netif = netif->next) {
#if IP_DEBUG
LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest "));
ip_addr_debug_print(IP_DEBUG, &(iphdr->dest));
LWIP_DEBUGF(IP_DEBUG, ("netif->ip_addr "));
ip_addr_debug_print(IP_DEBUG, &(netif->ip_addr));
LWIP_DEBUGF(IP_DEBUG, ("\n"));
#endif /* IP_DEBUG */
if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr))) {
break;
}
}
if (netif == NULL) {
/* packet not for us, route or discard */
#ifdef IP_FORWARD
ip_forward(p, iphdr);
#endif
pbuf_free(p);
return;
}
pbuf_realloc(p, IP_HLEN + ntohs(iphdr->len));
/* send to upper layers */
#if IP_DEBUG
/* LWIP_DEBUGF("ip_input: \n");
ip_debug_print(p);
LWIP_DEBUGF("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len);*/
#endif /* IP_DEBUG */
pbuf_header(p, -IP_HLEN);
switch (iphdr->nexthdr) {
case IP_PROTO_UDP:
udp_input(p);
break;
case IP_PROTO_TCP:
tcp_input(p);
break;
case IP_PROTO_ICMP:
icmp_input(p, inp);
break;
default:
/* send ICMP destination protocol unreachable */
icmp_dest_unreach(p, ICMP_DUR_PROTO);
pbuf_free(p);
LWIP_DEBUGF(IP_DEBUG, ("Unsupported transport protocol %"U16_F"\n",
iphdr->nexthdr));
#ifdef IP_STATS
++lwip_stats.ip.proterr;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
}
PERF_STOP("ip_input");
}
/* ip_output_if:
*
* Sends an IP packet on a network interface. This function constructs the IP header
* and calculates the IP header checksum. If the source IP address is NULL,
* the IP address of the outgoing network interface is filled in as source address.
*/
err_t
ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl,
u8_t proto, struct netif *netif)
{
struct ip_hdr *iphdr;
PERF_START;
printf("len %"U16_F" tot_len %"U16_F"\n", p->len, p->tot_len);
if (pbuf_header(p, IP_HLEN)) {
LWIP_DEBUGF(IP_DEBUG, ("ip_output: not enough room for IP header in pbuf\n"));
#ifdef IP_STATS
++lwip_stats.ip.err;
#endif /* IP_STATS */
return ERR_BUF;
}
printf("len %"U16_F" tot_len %"U16_F"\n", p->len, p->tot_len);
iphdr = p->payload;
if (dest != IP_HDRINCL) {
printf("!IP_HDRLINCL\n");
iphdr->hoplim = ttl;
iphdr->nexthdr = proto;
iphdr->len = htons(p->tot_len - IP_HLEN);
ip_addr_set(&(iphdr->dest), dest);
iphdr->v = 6;
if (ip_addr_isany(src)) {
ip_addr_set(&(iphdr->src), &(netif->ip_addr));
} else {
ip_addr_set(&(iphdr->src), src);
}
} else {
dest = &(iphdr->dest);
}
#ifdef IP_STATS
++lwip_stats.ip.xmit;
#endif /* IP_STATS */
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c (len %"U16_F")\n", netif->name[0], netif->name[1], p->tot_len));
#if IP_DEBUG
ip_debug_print(p);
#endif /* IP_DEBUG */
PERF_STOP("ip_output_if");
return netif->output(netif, p, dest);
}
/* ip_output:
*
* Simple interface to ip_output_if. It finds the outgoing network interface and
* calls upon ip_output_if to do the actual work.
*/
err_t
ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t proto)
{
struct netif *netif;
if ((netif = ip_route(dest)) == NULL) {
LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr));
#ifdef IP_STATS
++lwip_stats.ip.rterr;
#endif /* IP_STATS */
return ERR_RTE;
}
return ip_output_if (p, src, dest, ttl, proto, netif);
}
#if IP_DEBUG
void
ip_debug_print(struct pbuf *p)
{
struct ip_hdr *iphdr = p->payload;
u8_t *payload;
payload = (u8_t *)iphdr + IP_HLEN;
LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" | %"X16_F"%"X16_F" | %"X16_F"%"X16_F" | (v, traffic class, flow label)\n",
iphdr->v,
iphdr->tclass1, iphdr->tclass2,
iphdr->flow1, iphdr->flow2));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" | %2"U16_F" | %2"U16_F" | (len, nexthdr, hoplim)\n",
ntohs(iphdr->len),
iphdr->nexthdr,
iphdr->hoplim));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n",
ntohl(iphdr->src.addr[0]) >> 16 & 0xffff,
ntohl(iphdr->src.addr[0]) & 0xffff));
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n",
ntohl(iphdr->src.addr[1]) >> 16 & 0xffff,
ntohl(iphdr->src.addr[1]) & 0xffff));
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n",
ntohl(iphdr->src.addr[2]) >> 16 & 0xffff,
ntohl(iphdr->src.addr[2]) & 0xffff));
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n",
ntohl(iphdr->src.addr[3]) >> 16 & 0xffff,
ntohl(iphdr->src.addr[3]) & 0xffff));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n",
ntohl(iphdr->dest.addr[0]) >> 16 & 0xffff,
ntohl(iphdr->dest.addr[0]) & 0xffff));
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n",
ntohl(iphdr->dest.addr[1]) >> 16 & 0xffff,
ntohl(iphdr->dest.addr[1]) & 0xffff));
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n",
ntohl(iphdr->dest.addr[2]) >> 16 & 0xffff,
ntohl(iphdr->dest.addr[2]) & 0xffff));
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n",
ntohl(iphdr->dest.addr[3]) >> 16 & 0xffff,
ntohl(iphdr->dest.addr[3]) & 0xffff));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
}
#endif /* IP_DEBUG */

View File

@@ -0,0 +1,90 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/ip_addr.h"
#include "lwip/inet.h"
u8_t
ip_addr_netcmp(struct ip_addr *addr1, struct ip_addr *addr2,
struct ip_addr *mask)
{
return((addr1->addr[0] & mask->addr[0]) == (addr2->addr[0] & mask->addr[0]) &&
(addr1->addr[1] & mask->addr[1]) == (addr2->addr[1] & mask->addr[1]) &&
(addr1->addr[2] & mask->addr[2]) == (addr2->addr[2] & mask->addr[2]) &&
(addr1->addr[3] & mask->addr[3]) == (addr2->addr[3] & mask->addr[3]));
}
u8_t
ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2)
{
return(addr1->addr[0] == addr2->addr[0] &&
addr1->addr[1] == addr2->addr[1] &&
addr1->addr[2] == addr2->addr[2] &&
addr1->addr[3] == addr2->addr[3]);
}
void
ip_addr_set(struct ip_addr *dest, struct ip_addr *src)
{
memcpy(dest, src, sizeof(struct ip_addr));
/* dest->addr[0] = src->addr[0];
dest->addr[1] = src->addr[1];
dest->addr[2] = src->addr[2];
dest->addr[3] = src->addr[3];*/
}
u8_t
ip_addr_isany(struct ip_addr *addr)
{
if (addr == NULL) return 1;
return((addr->addr[0] | addr->addr[1] | addr->addr[2] | addr->addr[3]) == 0);
}
/*#if IP_DEBUG*/
void
ip_addr_debug_print(struct ip_addr *addr)
{
printf("%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F",
ntohl(addr->addr[0]) >> 16 & 0xffff,
ntohl(addr->addr[0]) & 0xffff,
ntohl(addr->addr[1]) >> 16 & 0xffff,
ntohl(addr->addr[1]) & 0xffff,
ntohl(addr->addr[2]) >> 16 & 0xffff,
ntohl(addr->addr[2]) & 0xffff,
ntohl(addr->addr[3]) >> 16 & 0xffff,
ntohl(addr->addr[3]) & 0xffff);
}
/*#endif*/ /* IP_DEBUG */

View File

@@ -0,0 +1,310 @@
/** @file
*
* Dynamic memory manager
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#include <string.h>
#include "lwip/arch.h"
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/sys.h"
#include "lwip/stats.h"
struct mem {
mem_size_t next, prev;
#if MEM_ALIGNMENT == 1
u8_t used;
#elif MEM_ALIGNMENT == 2
u16_t used;
#elif MEM_ALIGNMENT == 4
u32_t used;
#elif MEM_ALIGNMENT == 8
u64_t used;
#else
#error "unhandled MEM_ALIGNMENT size"
#endif /* MEM_ALIGNMENT */
};
static struct mem *ram_end;
static u8_t ram[MEM_SIZE + sizeof(struct mem) + MEM_ALIGNMENT];
#define MIN_SIZE 12
#if 0 /* this one does not align correctly for some, resulting in crashes */
#define SIZEOF_STRUCT_MEM (unsigned int)MEM_ALIGN_SIZE(sizeof(struct mem))
#else
#define SIZEOF_STRUCT_MEM (sizeof(struct mem) + \
(((sizeof(struct mem) % MEM_ALIGNMENT) == 0)? 0 : \
(4 - (sizeof(struct mem) % MEM_ALIGNMENT))))
#endif
static struct mem *lfree; /* pointer to the lowest free block */
static sys_sem_t mem_sem;
static void
plug_holes(struct mem *mem)
{
struct mem *nmem;
struct mem *pmem;
LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram);
LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end);
LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0);
/* plug hole forward */
LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE", mem->next <= MEM_SIZE);
nmem = (struct mem *)&ram[mem->next];
if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) {
if (lfree == nmem) {
lfree = mem;
}
mem->next = nmem->next;
((struct mem *)&ram[nmem->next])->prev = (u8_t *)mem - ram;
}
/* plug hole backward */
pmem = (struct mem *)&ram[mem->prev];
if (pmem != mem && pmem->used == 0) {
if (lfree == mem) {
lfree = pmem;
}
pmem->next = mem->next;
((struct mem *)&ram[mem->next])->prev = (u8_t *)pmem - ram;
}
}
void
mem_init(void)
{
struct mem *mem;
memset(ram, 0, MEM_SIZE);
mem = (struct mem *)ram;
mem->next = MEM_SIZE;
mem->prev = 0;
mem->used = 0;
ram_end = (struct mem *)&ram[MEM_SIZE];
ram_end->used = 1;
ram_end->next = MEM_SIZE;
ram_end->prev = MEM_SIZE;
mem_sem = sys_sem_new(1);
lfree = (struct mem *)ram;
#if MEM_STATS
lwip_stats.mem.avail = MEM_SIZE;
#endif /* MEM_STATS */
}
void
mem_free(void *rmem)
{
struct mem *mem;
if (rmem == NULL) {
LWIP_DEBUGF(MEM_DEBUG | DBG_TRACE | 2, ("mem_free(p == NULL) was called.\n"));
return;
}
sys_sem_wait(mem_sem);
LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
(u8_t *)rmem < (u8_t *)ram_end);
if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_free: illegal memory\n"));
#if MEM_STATS
++lwip_stats.mem.err;
#endif /* MEM_STATS */
sys_sem_signal(mem_sem);
return;
}
mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
LWIP_ASSERT("mem_free: mem->used", mem->used);
mem->used = 0;
if (mem < lfree) {
lfree = mem;
}
#if MEM_STATS
lwip_stats.mem.used -= mem->next - ((u8_t *)mem - ram);
#endif /* MEM_STATS */
plug_holes(mem);
sys_sem_signal(mem_sem);
}
void *
mem_reallocm(void *rmem, mem_size_t newsize)
{
void *nmem;
nmem = mem_malloc(newsize);
if (nmem == NULL) {
return mem_realloc(rmem, newsize);
}
memcpy(nmem, rmem, newsize);
mem_free(rmem);
return nmem;
}
void *
mem_realloc(void *rmem, mem_size_t newsize)
{
mem_size_t size;
mem_size_t ptr, ptr2;
struct mem *mem, *mem2;
/* Expand the size of the allocated memory region so that we can
adjust for alignment. */
if ((newsize % MEM_ALIGNMENT) != 0) {
newsize += MEM_ALIGNMENT - ((newsize + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT);
}
if (newsize > MEM_SIZE) {
return NULL;
}
sys_sem_wait(mem_sem);
LWIP_ASSERT("mem_realloc: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
(u8_t *)rmem < (u8_t *)ram_end);
if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_realloc: illegal memory\n"));
return rmem;
}
mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
ptr = (u8_t *)mem - ram;
size = mem->next - ptr - SIZEOF_STRUCT_MEM;
#if MEM_STATS
lwip_stats.mem.used -= (size - newsize);
#endif /* MEM_STATS */
if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE < size) {
ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
mem2 = (struct mem *)&ram[ptr2];
mem2->used = 0;
mem2->next = mem->next;
mem2->prev = ptr;
mem->next = ptr2;
if (mem2->next != MEM_SIZE) {
((struct mem *)&ram[mem2->next])->prev = ptr2;
}
plug_holes(mem2);
}
sys_sem_signal(mem_sem);
return rmem;
}
void *
mem_malloc(mem_size_t size)
{
mem_size_t ptr, ptr2;
struct mem *mem, *mem2;
if (size == 0) {
return NULL;
}
/* Expand the size of the allocated memory region so that we can
adjust for alignment. */
if ((size % MEM_ALIGNMENT) != 0) {
size += MEM_ALIGNMENT - ((size + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT);
}
if (size > MEM_SIZE) {
return NULL;
}
sys_sem_wait(mem_sem);
for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE; ptr = ((struct mem *)&ram[ptr])->next) {
mem = (struct mem *)&ram[ptr];
if (!mem->used &&
mem->next - (ptr + SIZEOF_STRUCT_MEM) >= size + SIZEOF_STRUCT_MEM) {
ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
mem2 = (struct mem *)&ram[ptr2];
mem2->prev = ptr;
mem2->next = mem->next;
mem->next = ptr2;
if (mem2->next != MEM_SIZE) {
((struct mem *)&ram[mem2->next])->prev = ptr2;
}
mem2->used = 0;
mem->used = 1;
#if MEM_STATS
lwip_stats.mem.used += (size + SIZEOF_STRUCT_MEM);
/* if (lwip_stats.mem.max < lwip_stats.mem.used) {
lwip_stats.mem.max = lwip_stats.mem.used;
} */
if (lwip_stats.mem.max < ptr2) {
lwip_stats.mem.max = ptr2;
}
#endif /* MEM_STATS */
if (mem == lfree) {
/* Find next free block after mem */
while (lfree->used && lfree != ram_end) {
lfree = (struct mem *)&ram[lfree->next];
}
LWIP_ASSERT("mem_malloc: !lfree->used", !lfree->used);
}
sys_sem_signal(mem_sem);
LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
(mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
(unsigned long)((u8_t *)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
return (u8_t *)mem + SIZEOF_STRUCT_MEM;
}
}
LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));
#if MEM_STATS
++lwip_stats.mem.err;
#endif /* MEM_STATS */
sys_sem_signal(mem_sem);
return NULL;
}

View File

@@ -0,0 +1,274 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/opt.h"
#include "lwip/memp.h"
#include "lwip/pbuf.h"
#include "lwip/udp.h"
#include "lwip/raw.h"
#include "lwip/tcp.h"
#include "lwip/api.h"
#include "lwip/api_msg.h"
#include "lwip/tcpip.h"
#include "lwip/sys.h"
#include "lwip/stats.h"
struct memp {
struct memp *next;
};
static struct memp *memp_tab[MEMP_MAX];
static const u16_t memp_sizes[MEMP_MAX] = {
sizeof(struct pbuf),
sizeof(struct raw_pcb),
sizeof(struct udp_pcb),
sizeof(struct tcp_pcb),
sizeof(struct tcp_pcb_listen),
sizeof(struct tcp_seg),
sizeof(struct netbuf),
sizeof(struct netconn),
sizeof(struct api_msg),
sizeof(struct tcpip_msg),
sizeof(struct sys_timeout)
};
static const u16_t memp_num[MEMP_MAX] = {
MEMP_NUM_PBUF,
MEMP_NUM_RAW_PCB,
MEMP_NUM_UDP_PCB,
MEMP_NUM_TCP_PCB,
MEMP_NUM_TCP_PCB_LISTEN,
MEMP_NUM_TCP_SEG,
MEMP_NUM_NETBUF,
MEMP_NUM_NETCONN,
MEMP_NUM_API_MSG,
MEMP_NUM_TCPIP_MSG,
MEMP_NUM_SYS_TIMEOUT
};
static u8_t memp_memory[(MEMP_NUM_PBUF *
MEM_ALIGN_SIZE(sizeof(struct pbuf) +
sizeof(struct memp)) +
MEMP_NUM_RAW_PCB *
MEM_ALIGN_SIZE(sizeof(struct raw_pcb) +
sizeof(struct memp)) +
MEMP_NUM_UDP_PCB *
MEM_ALIGN_SIZE(sizeof(struct udp_pcb) +
sizeof(struct memp)) +
MEMP_NUM_TCP_PCB *
MEM_ALIGN_SIZE(sizeof(struct tcp_pcb) +
sizeof(struct memp)) +
MEMP_NUM_TCP_PCB_LISTEN *
MEM_ALIGN_SIZE(sizeof(struct tcp_pcb_listen) +
sizeof(struct memp)) +
MEMP_NUM_TCP_SEG *
MEM_ALIGN_SIZE(sizeof(struct tcp_seg) +
sizeof(struct memp)) +
MEMP_NUM_NETBUF *
MEM_ALIGN_SIZE(sizeof(struct netbuf) +
sizeof(struct memp)) +
MEMP_NUM_NETCONN *
MEM_ALIGN_SIZE(sizeof(struct netconn) +
sizeof(struct memp)) +
MEMP_NUM_API_MSG *
MEM_ALIGN_SIZE(sizeof(struct api_msg) +
sizeof(struct memp)) +
MEMP_NUM_TCPIP_MSG *
MEM_ALIGN_SIZE(sizeof(struct tcpip_msg) +
sizeof(struct memp)) +
MEMP_NUM_SYS_TIMEOUT *
MEM_ALIGN_SIZE(sizeof(struct sys_timeout) +
sizeof(struct memp)))];
#if !SYS_LIGHTWEIGHT_PROT
static sys_sem_t mutex;
#endif
#if MEMP_SANITY_CHECK
static int
memp_sanity(void)
{
s16_t i, c;
struct memp *m, *n;
for(i = 0; i < MEMP_MAX; i++) {
for(m = memp_tab[i]; m != NULL; m = m->next) {
c = 1;
for(n = memp_tab[i]; n != NULL; n = n->next) {
if (n == m) {
--c;
}
if (c < 0) return 0; /* LW was: abort(); */
}
}
}
return 1;
}
#endif /* MEMP_SANITY_CHECK*/
void
memp_init(void)
{
struct memp *m, *memp;
u16_t i, j;
u16_t size;
#if MEMP_STATS
for(i = 0; i < MEMP_MAX; ++i) {
lwip_stats.memp[i].used = lwip_stats.memp[i].max =
lwip_stats.memp[i].err = 0;
lwip_stats.memp[i].avail = memp_num[i];
}
#endif /* MEMP_STATS */
memp = (struct memp *)&memp_memory[0];
for(i = 0; i < MEMP_MAX; ++i) {
size = MEM_ALIGN_SIZE(memp_sizes[i] + sizeof(struct memp));
if (memp_num[i] > 0) {
memp_tab[i] = memp;
m = memp;
for(j = 0; j < memp_num[i]; ++j) {
m->next = (struct memp *)MEM_ALIGN((u8_t *)m + size);
memp = m;
m = m->next;
}
memp->next = NULL;
memp = m;
} else {
memp_tab[i] = NULL;
}
}
#if !SYS_LIGHTWEIGHT_PROT
mutex = sys_sem_new(1);
#endif
}
void *
memp_malloc(memp_t type)
{
struct memp *memp;
void *mem;
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_DECL_PROTECT(old_level);
#endif
LWIP_ASSERT("memp_malloc: type < MEMP_MAX", type < MEMP_MAX);
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_PROTECT(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_wait(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */
memp = memp_tab[type];
if (memp != NULL) {
memp_tab[type] = memp->next;
memp->next = NULL;
#if MEMP_STATS
++lwip_stats.memp[type].used;
if (lwip_stats.memp[type].used > lwip_stats.memp[type].max) {
lwip_stats.memp[type].max = lwip_stats.memp[type].used;
}
#endif /* MEMP_STATS */
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_UNPROTECT(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_signal(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */
LWIP_ASSERT("memp_malloc: memp properly aligned",
((mem_ptr_t)MEM_ALIGN((u8_t *)memp + sizeof(struct memp)) % MEM_ALIGNMENT) == 0);
mem = MEM_ALIGN((u8_t *)memp + sizeof(struct memp));
return mem;
} else {
LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %"S16_F"\n", type));
#if MEMP_STATS
++lwip_stats.memp[type].err;
#endif /* MEMP_STATS */
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_UNPROTECT(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_signal(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */
return NULL;
}
}
void
memp_free(memp_t type, void *mem)
{
struct memp *memp;
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_DECL_PROTECT(old_level);
#endif /* SYS_LIGHTWEIGHT_PROT */
if (mem == NULL) {
return;
}
memp = (struct memp *)((u8_t *)mem - sizeof(struct memp));
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_PROTECT(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_wait(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */
#if MEMP_STATS
lwip_stats.memp[type].used--;
#endif /* MEMP_STATS */
memp->next = memp_tab[type];
memp_tab[type] = memp;
#if MEMP_SANITY_CHECK
LWIP_ASSERT("memp sanity", memp_sanity());
#endif
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_UNPROTECT(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_signal(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */
}

View File

@@ -0,0 +1,288 @@
/**
* @file
*
* lwIP network interface abstraction
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#include "lwip/tcp.h"
struct netif *netif_list = NULL;
struct netif *netif_default = NULL;
/**
* Add a network interface to the list of lwIP netifs.
*
* @param netif a pre-allocated netif structure
* @param ipaddr IP address for the new netif
* @param netmask network mask for the new netif
* @param gw default gateway IP address for the new netif
* @param state opaque data passed to the new netif
* @param init callback function that initializes the interface
* @param input callback function that is called to pass
* ingress packets up in the protocol layer stack.
*
* @return netif, or NULL if failed.
*/
struct netif *
netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
struct ip_addr *gw,
void *state,
err_t (* init)(struct netif *netif),
err_t (* input)(struct pbuf *p, struct netif *netif))
{
static s16_t netifnum = 0;
#if LWIP_DHCP
/* netif not under DHCP control by default */
netif->dhcp = NULL;
#endif
/* remember netif specific state information data */
netif->state = state;
netif->num = netifnum++;
netif->input = input;
netif_set_addr(netif, ipaddr, netmask, gw);
/* call user specified initialization function for netif */
if (init(netif) != ERR_OK) {
return NULL;
}
/* add this netif to the list */
netif->next = netif_list;
netif_list = netif;
LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ",
netif->name[0], netif->name[1]));
ip_addr_debug_print(NETIF_DEBUG, ipaddr);
LWIP_DEBUGF(NETIF_DEBUG, (" netmask "));
ip_addr_debug_print(NETIF_DEBUG, netmask);
LWIP_DEBUGF(NETIF_DEBUG, (" gw "));
ip_addr_debug_print(NETIF_DEBUG, gw);
LWIP_DEBUGF(NETIF_DEBUG, ("\n"));
return netif;
}
void
netif_set_addr(struct netif *netif,struct ip_addr *ipaddr, struct ip_addr *netmask,
struct ip_addr *gw)
{
netif_set_ipaddr(netif, ipaddr);
netif_set_netmask(netif, netmask);
netif_set_gw(netif, gw);
}
void netif_remove(struct netif * netif)
{
if ( netif == NULL ) return;
/* is it the first netif? */
if (netif_list == netif) {
netif_list = netif->next;
}
else {
/* look for netif further down the list */
struct netif * tmpNetif;
for (tmpNetif = netif_list; tmpNetif != NULL; tmpNetif = tmpNetif->next) {
if (tmpNetif->next == netif) {
tmpNetif->next = netif->next;
break;
}
}
if (tmpNetif == NULL)
return; /* we didn't find any netif today */
}
/* this netif is default? */
if (netif_default == netif)
/* reset default netif */
netif_default = NULL;
LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") );
}
struct netif *
netif_find(char *name)
{
struct netif *netif;
u8_t num;
if (name == NULL) {
return NULL;
}
num = name[2] - '0';
for(netif = netif_list; netif != NULL; netif = netif->next) {
if (num == netif->num &&
name[0] == netif->name[0] &&
name[1] == netif->name[1]) {
LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1]));
return netif;
}
}
LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1]));
return NULL;
}
void
netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
{
/* TODO: Handling of obsolete pcbs */
/* See: http://mail.gnu.org/archive/html/lwip-users/2003-03/msg00118.html */
#if LWIP_TCP
struct tcp_pcb *pcb;
struct tcp_pcb_listen *lpcb;
/* address is actually being changed? */
if ((ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0)
{
/* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */
LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: netif address being changed\n"));
pcb = tcp_active_pcbs;
while (pcb != NULL) {
/* PCB bound to current local interface address? */
if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) {
/* this connection must be aborted */
struct tcp_pcb *next = pcb->next;
LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb));
tcp_abort(pcb);
pcb = next;
} else {
pcb = pcb->next;
}
}
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
/* PCB bound to current local interface address? */
if (ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr))) {
/* The PCB is listening to the old ipaddr and
* is set to listen to the new one instead */
ip_addr_set(&(lpcb->local_ip), ipaddr);
}
}
}
#endif
ip_addr_set(&(netif->ip_addr), ipaddr);
#if 0 /* only allowed for Ethernet interfaces TODO: how can we check? */
/** For Ethernet network interfaces, we would like to send a
* "gratuitous ARP"; this is an ARP packet sent by a node in order
* to spontaneously cause other nodes to update an entry in their
* ARP cache. From RFC 3220 "IP Mobility Support for IPv4" section 4.6.
*/
etharp_query(netif, ipaddr, NULL);
#endif
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
netif->name[0], netif->name[1],
ip4_addr1(&netif->ip_addr),
ip4_addr2(&netif->ip_addr),
ip4_addr3(&netif->ip_addr),
ip4_addr4(&netif->ip_addr)));
}
void
netif_set_gw(struct netif *netif, struct ip_addr *gw)
{
ip_addr_set(&(netif->gw), gw);
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
netif->name[0], netif->name[1],
ip4_addr1(&netif->gw),
ip4_addr2(&netif->gw),
ip4_addr3(&netif->gw),
ip4_addr4(&netif->gw)));
}
void
netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
{
ip_addr_set(&(netif->netmask), netmask);
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
netif->name[0], netif->name[1],
ip4_addr1(&netif->netmask),
ip4_addr2(&netif->netmask),
ip4_addr3(&netif->netmask),
ip4_addr4(&netif->netmask)));
}
void
netif_set_default(struct netif *netif)
{
netif_default = netif;
LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n",
netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\''));
}
/**
* Bring an interface up, available for processing
* traffic.
*
* @note: Enabling DHCP on a down interface will make it come
* up once configured.
*
* @see dhcp_start()
*/
void netif_set_up(struct netif *netif)
{
netif->flags |= NETIF_FLAG_UP;
}
/**
* Ask if an interface is up
*/
u8_t netif_is_up(struct netif *netif)
{
return (netif->flags & NETIF_FLAG_UP)?1:0;
}
/**
* Bring an interface down, disabling any traffic processing.
*
* @note: Enabling DHCP on a down interface will make it come
* up once configured.
*
* @see dhcp_start()
*/
void netif_set_down(struct netif *netif)
{
netif->flags &= ~NETIF_FLAG_UP;
}
void
netif_init(void)
{
netif_list = netif_default = NULL;
}

View File

@@ -0,0 +1,957 @@
/**
* @file
* Packet buffer management
*
* Packets are built from the pbuf data structure. It supports dynamic
* memory allocation for packet contents or can reference externally
* managed packet contents both in RAM and ROM. Quick allocation for
* incoming packets is provided through pools with fixed sized pbufs.
*
* A packet may span over multiple pbufs, chained as a singly linked
* list. This is called a "pbuf chain".
*
* Multiple packets may be queued, also using this singly linked list.
* This is called a "packet queue".
*
* So, a packet queue consists of one or more pbuf chains, each of
* which consist of one or more pbufs. Currently, queues are only
* supported in a limited section of lwIP, this is the etharp queueing
* code. Outside of this section no packet queues are supported yet.
*
* The differences between a pbuf chain and a packet queue are very
* precise but subtle.
*
* The last pbuf of a packet has a ->tot_len field that equals the
* ->len field. It can be found by traversing the list. If the last
* pbuf of a packet has a ->next field other than NULL, more packets
* are on the queue.
*
* Therefore, looping through a pbuf of a single packet, has an
* loop end condition (tot_len == p->len), NOT (next == NULL).
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#include <string.h>
#include "lwip/opt.h"
#include "lwip/stats.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include "arch/perf.h"
static u8_t pbuf_pool_memory[MEM_ALIGNMENT - 1 + PBUF_POOL_SIZE * MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE + sizeof(struct pbuf))];
#if !SYS_LIGHTWEIGHT_PROT
static volatile u8_t pbuf_pool_free_lock, pbuf_pool_alloc_lock;
static sys_sem_t pbuf_pool_free_sem;
#endif
static struct pbuf *pbuf_pool = NULL;
/**
* Initializes the pbuf module.
*
* A large part of memory is allocated for holding the pool of pbufs.
* The size of the individual pbufs in the pool is given by the size
* parameter, and the number of pbufs in the pool by the num parameter.
*
* After the memory has been allocated, the pbufs are set up. The
* ->next pointer in each pbuf is set up to point to the next pbuf in
* the pool.
*
*/
void
pbuf_init(void)
{
struct pbuf *p, *q = NULL;
u16_t i;
pbuf_pool = (struct pbuf *)MEM_ALIGN(pbuf_pool_memory);
#if PBUF_STATS
lwip_stats.pbuf.avail = PBUF_POOL_SIZE;
#endif /* PBUF_STATS */
/* Set up ->next pointers to link the pbufs of the pool together */
p = pbuf_pool;
for(i = 0; i < PBUF_POOL_SIZE; ++i) {
p->next = (struct pbuf *)((u8_t *)p + PBUF_POOL_BUFSIZE + sizeof(struct pbuf));
p->len = p->tot_len = PBUF_POOL_BUFSIZE;
p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf)));
p->flags = PBUF_FLAG_POOL;
q = p;
p = p->next;
}
/* The ->next pointer of last pbuf is NULL to indicate that there
are no more pbufs in the pool */
q->next = NULL;
#if !SYS_LIGHTWEIGHT_PROT
pbuf_pool_alloc_lock = 0;
pbuf_pool_free_lock = 0;
pbuf_pool_free_sem = sys_sem_new(1);
#endif
}
/**
* @internal only called from pbuf_alloc()
*/
static struct pbuf *
pbuf_pool_alloc(void)
{
struct pbuf *p = NULL;
SYS_ARCH_DECL_PROTECT(old_level);
SYS_ARCH_PROTECT(old_level);
#if !SYS_LIGHTWEIGHT_PROT
/* Next, check the actual pbuf pool, but if the pool is locked, we
pretend to be out of buffers and return NULL. */
if (pbuf_pool_free_lock) {
#if PBUF_STATS
++lwip_stats.pbuf.alloc_locked;
#endif /* PBUF_STATS */
return NULL;
}
pbuf_pool_alloc_lock = 1;
if (!pbuf_pool_free_lock) {
#endif /* SYS_LIGHTWEIGHT_PROT */
p = pbuf_pool;
if (p) {
pbuf_pool = p->next;
}
#if !SYS_LIGHTWEIGHT_PROT
#if PBUF_STATS
} else {
++lwip_stats.pbuf.alloc_locked;
#endif /* PBUF_STATS */
}
pbuf_pool_alloc_lock = 0;
#endif /* SYS_LIGHTWEIGHT_PROT */
#if PBUF_STATS
if (p != NULL) {
++lwip_stats.pbuf.used;
if (lwip_stats.pbuf.used > lwip_stats.pbuf.max) {
lwip_stats.pbuf.max = lwip_stats.pbuf.used;
}
}
#endif /* PBUF_STATS */
SYS_ARCH_UNPROTECT(old_level);
return p;
}
/**
* Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type).
*
* The actual memory allocated for the pbuf is determined by the
* layer at which the pbuf is allocated and the requested size
* (from the size parameter).
*
* @param flag this parameter decides how and where the pbuf
* should be allocated as follows:
*
* - PBUF_RAM: buffer memory for pbuf is allocated as one large
* chunk. This includes protocol headers as well.
* - PBUF_ROM: no buffer memory is allocated for the pbuf, even for
* protocol headers. Additional headers must be prepended
* by allocating another pbuf and chain in to the front of
* the ROM pbuf. It is assumed that the memory used is really
* similar to ROM in that it is immutable and will not be
* changed. Memory which is dynamic should generally not
* be attached to PBUF_ROM pbufs. Use PBUF_REF instead.
* - PBUF_REF: no buffer memory is allocated for the pbuf, even for
* protocol headers. It is assumed that the pbuf is only
* being used in a single thread. If the pbuf gets queued,
* then pbuf_take should be called to copy the buffer.
* - PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from
* the pbuf pool that is allocated during pbuf_init().
*
* @return the allocated pbuf. If multiple pbufs where allocated, this
* is the first pbuf of a pbuf chain.
*/
struct pbuf *
pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
{
struct pbuf *p, *q, *r;
u16_t offset;
s32_t rem_len; /* remaining length */
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%"U16_F")\n", length));
/* determine header offset */
offset = 0;
switch (l) {
case PBUF_TRANSPORT:
/* add room for transport (often TCP) layer header */
offset += PBUF_TRANSPORT_HLEN;
/* FALLTHROUGH */
case PBUF_IP:
/* add room for IP layer header */
offset += PBUF_IP_HLEN;
/* FALLTHROUGH */
case PBUF_LINK:
/* add room for link layer header */
offset += PBUF_LINK_HLEN;
break;
case PBUF_RAW:
break;
default:
LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0);
return NULL;
}
switch (flag) {
case PBUF_POOL:
/* allocate head of pbuf chain into p */
p = pbuf_pool_alloc();
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc: allocated pbuf %p\n", (void *)p));
if (p == NULL) {
#if PBUF_STATS
++lwip_stats.pbuf.err;
#endif /* PBUF_STATS */
return NULL;
}
p->next = NULL;
/* make the payload pointer point 'offset' bytes into pbuf data memory */
p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset)));
LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned",
((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
/* the total length of the pbuf chain is the requested size */
p->tot_len = length;
/* set the length of the first pbuf in the chain */
p->len = length > PBUF_POOL_BUFSIZE - offset? PBUF_POOL_BUFSIZE - offset: length;
/* set reference count (needed here in case we fail) */
p->ref = 1;
/* now allocate the tail of the pbuf chain */
/* remember first pbuf for linkage in next iteration */
r = p;
/* remaining length to be allocated */
rem_len = length - p->len;
/* any remaining pbufs to be allocated? */
while (rem_len > 0) {
q = pbuf_pool_alloc();
if (q == NULL) {
LWIP_DEBUGF(PBUF_DEBUG | 2, ("pbuf_alloc: Out of pbufs in pool.\n"));
#if PBUF_STATS
++lwip_stats.pbuf.err;
#endif /* PBUF_STATS */
/* free chain so far allocated */
pbuf_free(p);
/* bail out unsuccesfully */
return NULL;
}
q->next = NULL;
/* make previous pbuf point to this pbuf */
r->next = q;
/* set total length of this pbuf and next in chain */
q->tot_len = rem_len;
/* this pbuf length is pool size, unless smaller sized tail */
q->len = rem_len > PBUF_POOL_BUFSIZE? PBUF_POOL_BUFSIZE: rem_len;
q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));
LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned",
((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0);
q->ref = 1;
/* calculate remaining length to be allocated */
rem_len -= q->len;
/* remember this pbuf for linkage in next iteration */
r = q;
}
/* end of chain */
/*r->next = NULL;*/
break;
case PBUF_RAM:
/* If pbuf is to be allocated in RAM, allocate memory for it. */
p = mem_malloc(MEM_ALIGN_SIZE(sizeof(struct pbuf) + offset) + MEM_ALIGN_SIZE(length));
if (p == NULL) {
return NULL;
}
/* Set up internal structure of the pbuf. */
p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf) + offset));
p->len = p->tot_len = length;
p->next = NULL;
p->flags = PBUF_FLAG_RAM;
LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",
((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
break;
/* pbuf references existing (non-volatile static constant) ROM payload? */
case PBUF_ROM:
/* pbuf references existing (externally allocated) RAM payload? */
case PBUF_REF:
/* only allocate memory for the pbuf structure */
p = memp_malloc(MEMP_PBUF);
if (p == NULL) {
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n", flag == PBUF_ROM?"ROM":"REF"));
return NULL;
}
/* caller must set this field properly, afterwards */
p->payload = NULL;
p->len = p->tot_len = length;
p->next = NULL;
p->flags = (flag == PBUF_ROM? PBUF_FLAG_ROM: PBUF_FLAG_REF);
break;
default:
LWIP_ASSERT("pbuf_alloc: erroneous flag", 0);
return NULL;
}
/* set reference count */
p->ref = 1;
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p));
return p;
}
#if PBUF_STATS
#define DEC_PBUF_STATS do { --lwip_stats.pbuf.used; } while (0)
#else /* PBUF_STATS */
#define DEC_PBUF_STATS
#endif /* PBUF_STATS */
#define PBUF_POOL_FAST_FREE(p) do { \
p->next = pbuf_pool; \
pbuf_pool = p; \
DEC_PBUF_STATS; \
} while (0)
#if SYS_LIGHTWEIGHT_PROT
#define PBUF_POOL_FREE(p) do { \
SYS_ARCH_DECL_PROTECT(old_level); \
SYS_ARCH_PROTECT(old_level); \
PBUF_POOL_FAST_FREE(p); \
SYS_ARCH_UNPROTECT(old_level); \
} while (0)
#else /* SYS_LIGHTWEIGHT_PROT */
#define PBUF_POOL_FREE(p) do { \
sys_sem_wait(pbuf_pool_free_sem); \
PBUF_POOL_FAST_FREE(p); \
sys_sem_signal(pbuf_pool_free_sem); \
} while (0)
#endif /* SYS_LIGHTWEIGHT_PROT */
/**
* Shrink a pbuf chain to a desired length.
*
* @param p pbuf to shrink.
* @param new_len desired new length of pbuf chain
*
* Depending on the desired length, the first few pbufs in a chain might
* be skipped and left unchanged. The new last pbuf in the chain will be
* resized, and any remaining pbufs will be freed.
*
* @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted.
* @note May not be called on a packet queue.
*
* @bug Cannot grow the size of a pbuf (chain) (yet).
*/
void
pbuf_realloc(struct pbuf *p, u16_t new_len)
{
struct pbuf *q;
u16_t rem_len; /* remaining length */
s16_t grow;
LWIP_ASSERT("pbuf_realloc: sane p->flags", p->flags == PBUF_FLAG_POOL ||
p->flags == PBUF_FLAG_ROM ||
p->flags == PBUF_FLAG_RAM ||
p->flags == PBUF_FLAG_REF);
/* desired length larger than current length? */
if (new_len >= p->tot_len) {
/* enlarging not yet supported */
return;
}
/* the pbuf chain grows by (new_len - p->tot_len) bytes
* (which may be negative in case of shrinking) */
grow = new_len - p->tot_len;
/* first, step over any pbufs that should remain in the chain */
rem_len = new_len;
q = p;
/* should this pbuf be kept? */
while (rem_len > q->len) {
/* decrease remaining length by pbuf length */
rem_len -= q->len;
/* decrease total length indicator */
q->tot_len += grow;
/* proceed to next pbuf in chain */
q = q->next;
}
/* we have now reached the new last pbuf (in q) */
/* rem_len == desired length for pbuf q */
/* shrink allocated memory for PBUF_RAM */
/* (other types merely adjust their length fields */
if ((q->flags == PBUF_FLAG_RAM) && (rem_len != q->len)) {
/* reallocate and adjust the length of the pbuf that will be split */
mem_realloc(q, (u8_t *)q->payload - (u8_t *)q + rem_len);
}
/* adjust length fields for new last pbuf */
q->len = rem_len;
q->tot_len = q->len;
/* any remaining pbufs in chain? */
if (q->next != NULL) {
/* free remaining pbufs in chain */
pbuf_free(q->next);
}
/* q is last packet in chain */
q->next = NULL;
}
/**
* Adjusts the payload pointer to hide or reveal headers in the payload.
*
* Adjusts the ->payload pointer so that space for a header
* (dis)appears in the pbuf payload.
*
* The ->payload, ->tot_len and ->len fields are adjusted.
*
* @param hdr_size_inc Number of bytes to increment header size which
* increases the size of the pbuf. New space is on the front.
* (Using a negative value decreases the header size.)
* If hdr_size_inc is 0, this function does nothing and returns succesful.
*
* PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so
* the call will fail. A check is made that the increase in header size does
* not move the payload pointer in front of the start of the buffer.
* @return non-zero on failure, zero on success.
*
*/
u8_t
pbuf_header(struct pbuf *p, s16_t header_size_increment)
{
void *payload;
LWIP_ASSERT("p != NULL", p != NULL);
if ((header_size_increment == 0) || (p == NULL)) return 0;
/* remember current payload pointer */
payload = p->payload;
/* pbuf types containing payloads? */
if (p->flags == PBUF_FLAG_RAM || p->flags == PBUF_FLAG_POOL) {
/* set new payload pointer */
p->payload = (u8_t *)p->payload - header_size_increment;
/* boundary check fails? */
if ((u8_t *)p->payload < (u8_t *)p + sizeof(struct pbuf)) {
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_header: failed as %p < %p (not enough space for new header size)\n",
(void *)p->payload,
(void *)(p + 1)));\
/* restore old payload pointer */
p->payload = payload;
/* bail out unsuccesfully */
return 1;
}
/* pbuf types refering to external payloads? */
} else if (p->flags == PBUF_FLAG_REF || p->flags == PBUF_FLAG_ROM) {
/* hide a header in the payload? */
if ((header_size_increment < 0) && (header_size_increment - p->len <= 0)) {
/* increase payload pointer */
p->payload = (u8_t *)p->payload - header_size_increment;
} else {
/* cannot expand payload to front (yet!)
* bail out unsuccesfully */
return 1;
}
}
/* modify pbuf length fields */
p->len += header_size_increment;
p->tot_len += header_size_increment;
LWIP_DEBUGF( PBUF_DEBUG, ("pbuf_header: old %p new %p (%"S16_F")\n",
(void *)payload, (void *)p->payload, header_size_increment));
return 0;
}
/**
* Dereference a pbuf chain or queue and deallocate any no-longer-used
* pbufs at the head of this chain or queue.
*
* Decrements the pbuf reference count. If it reaches zero, the pbuf is
* deallocated.
*
* For a pbuf chain, this is repeated for each pbuf in the chain,
* up to the first pbuf which has a non-zero reference count after
* decrementing. So, when all reference counts are one, the whole
* chain is free'd.
*
* @param pbuf The pbuf (chain) to be dereferenced.
*
* @return the number of pbufs that were de-allocated
* from the head of the chain.
*
* @note MUST NOT be called on a packet queue (Not verified to work yet).
* @note the reference counter of a pbuf equals the number of pointers
* that refer to the pbuf (or into the pbuf).
*
* @internal examples:
*
* Assuming existing chains a->b->c with the following reference
* counts, calling pbuf_free(a) results in:
*
* 1->2->3 becomes ...1->3
* 3->3->3 becomes 2->3->3
* 1->1->2 becomes ......1
* 2->1->1 becomes 1->1->1
* 1->1->1 becomes .......
*
*/
u8_t
pbuf_free(struct pbuf *p)
{
struct pbuf *q;
u8_t count;
SYS_ARCH_DECL_PROTECT(old_level);
LWIP_ASSERT("p != NULL", p != NULL);
/* if assertions are disabled, proceed with debug output */
if (p == NULL) {
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_free(p == NULL) was called.\n"));
return 0;
}
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_free(%p)\n", (void *)p));
PERF_START;
LWIP_ASSERT("pbuf_free: sane flags",
p->flags == PBUF_FLAG_RAM || p->flags == PBUF_FLAG_ROM ||
p->flags == PBUF_FLAG_REF || p->flags == PBUF_FLAG_POOL);
count = 0;
/* Since decrementing ref cannot be guaranteed to be a single machine operation
* we must protect it. Also, the later test of ref must be protected.
*/
SYS_ARCH_PROTECT(old_level);
/* de-allocate all consecutive pbufs from the head of the chain that
* obtain a zero reference count after decrementing*/
while (p != NULL) {
/* all pbufs in a chain are referenced at least once */
LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0);
/* decrease reference count (number of pointers to pbuf) */
p->ref--;
/* this pbuf is no longer referenced to? */
if (p->ref == 0) {
/* remember next pbuf in chain for next iteration */
q = p->next;
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: deallocating %p\n", (void *)p));
/* is this a pbuf from the pool? */
if (p->flags == PBUF_FLAG_POOL) {
p->len = p->tot_len = PBUF_POOL_BUFSIZE;
p->payload = (void *)((u8_t *)p + sizeof(struct pbuf));
PBUF_POOL_FREE(p);
/* is this a ROM or RAM referencing pbuf? */
} else if (p->flags == PBUF_FLAG_ROM || p->flags == PBUF_FLAG_REF) {
memp_free(MEMP_PBUF, p);
/* p->flags == PBUF_FLAG_RAM */
} else {
mem_free(p);
}
count++;
/* proceed to next pbuf */
p = q;
/* p->ref > 0, this pbuf is still referenced to */
/* (and so the remaining pbufs in chain as well) */
} else {
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, (u16_t)p->ref));
/* stop walking through the chain */
p = NULL;
}
}
SYS_ARCH_UNPROTECT(old_level);
PERF_STOP("pbuf_free");
/* return number of de-allocated pbufs */
return count;
}
/**
* Count number of pbufs in a chain
*
* @param p first pbuf of chain
* @return the number of pbufs in a chain
*/
u8_t
pbuf_clen(struct pbuf *p)
{
u8_t len;
len = 0;
while (p != NULL) {
++len;
p = p->next;
}
return len;
}
/**
* Increment the reference count of the pbuf.
*
* @param p pbuf to increase reference counter of
*
*/
void
pbuf_ref(struct pbuf *p)
{
SYS_ARCH_DECL_PROTECT(old_level);
/* pbuf given? */
if (p != NULL) {
SYS_ARCH_PROTECT(old_level);
++(p->ref);
SYS_ARCH_UNPROTECT(old_level);
}
}
/**
* Concatenate two pbufs (each may be a pbuf chain) and take over
* the caller's reference of the tail pbuf.
*
* @note The caller MAY NOT reference the tail pbuf afterwards.
* Use pbuf_chain() for that purpose.
*
* @see pbuf_chain()
*/
void
pbuf_cat(struct pbuf *h, struct pbuf *t)
{
struct pbuf *p;
LWIP_ASSERT("h != NULL (programmer violates API)", h != NULL);
LWIP_ASSERT("t != NULL (programmer violates API)", t != NULL);
if ((h == NULL) || (t == NULL)) return;
/* proceed to last pbuf of chain */
for (p = h; p->next != NULL; p = p->next) {
/* add total length of second chain to all totals of first chain */
p->tot_len += t->tot_len;
}
/* { p is last pbuf of first h chain, p->next == NULL } */
LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len);
LWIP_ASSERT("p->next == NULL", p->next == NULL);
/* add total length of second chain to last pbuf total of first chain */
p->tot_len += t->tot_len;
/* chain last pbuf of head (p) with first of tail (t) */
p->next = t;
/* p->next now references t, but the caller will drop its reference to t,
* so netto there is no change to the reference count of t.
*/
}
/**
* Chain two pbufs (or pbuf chains) together.
*
* The caller MUST call pbuf_free(t) once it has stopped
* using it. Use pbuf_cat() instead if you no longer use t.
*
* @param h head pbuf (chain)
* @param t tail pbuf (chain)
* @note The pbufs MUST belong to the same packet.
* @note MAY NOT be called on a packet queue.
*
* The ->tot_len fields of all pbufs of the head chain are adjusted.
* The ->next field of the last pbuf of the head chain is adjusted.
* The ->ref field of the first pbuf of the tail chain is adjusted.
*
*/
void
pbuf_chain(struct pbuf *h, struct pbuf *t)
{
pbuf_cat(h, t);
/* t is now referenced by h */
pbuf_ref(t);
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t));
}
/* For packet queueing. Note that queued packets MUST be dequeued first
* using pbuf_dequeue() before calling other pbuf_() functions. */
#if ARP_QUEUEING
/**
* Add a packet to the end of a queue.
*
* @param q pointer to first packet on the queue
* @param n packet to be queued
*
* Both packets MUST be given, and must be different.
*/
void
pbuf_queue(struct pbuf *p, struct pbuf *n)
{
#if PBUF_DEBUG /* remember head of queue */
struct pbuf *q = p;
#endif
/* programmer stupidity checks */
LWIP_ASSERT("p == NULL in pbuf_queue: this indicates a programmer error\n", p != NULL);
LWIP_ASSERT("n == NULL in pbuf_queue: this indicates a programmer error\n", n != NULL);
LWIP_ASSERT("p == n in pbuf_queue: this indicates a programmer error\n", p != n);
if ((p == NULL) || (n == NULL) || (p == n)){
LWIP_DEBUGF(PBUF_DEBUG | DBG_HALT | 3, ("pbuf_queue: programmer argument error\n"));
return;
}
/* iterate through all packets on queue */
while (p->next != NULL) {
/* be very picky about pbuf chain correctness */
#if PBUF_DEBUG
/* iterate through all pbufs in packet */
while (p->tot_len != p->len) {
/* make sure invariant condition holds */
LWIP_ASSERT("p->len < p->tot_len", p->len < p->tot_len);
/* make sure each packet is complete */
LWIP_ASSERT("p->next != NULL", p->next != NULL);
p = p->next;
/* { p->tot_len == p->len => p is last pbuf of a packet } */
}
/* { p is last pbuf of a packet } */
/* proceed to next packet on queue */
#endif
/* proceed to next pbuf */
if (p->next != NULL) p = p->next;
}
/* { p->tot_len == p->len and p->next == NULL } ==>
* { p is last pbuf of last packet on queue } */
/* chain last pbuf of queue with n */
p->next = n;
/* n is now referenced to by the (packet p in the) queue */
pbuf_ref(n);
#if PBUF_DEBUG
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2,
("pbuf_queue: newly queued packet %p sits after packet %p in queue %p\n",
(void *)n, (void *)p, (void *)q));
#endif
}
/**
* Remove a packet from the head of a queue.
*
* The caller MUST reference the remainder of the queue (as returned). The
* caller MUST NOT call pbuf_ref() as it implicitly takes over the reference
* from p.
*
* @param p pointer to first packet on the queue which will be dequeued.
* @return first packet on the remaining queue (NULL if no further packets).
*
*/
struct pbuf *
pbuf_dequeue(struct pbuf *p)
{
struct pbuf *q;
LWIP_ASSERT("p != NULL", p != NULL);
/* iterate through all pbufs in packet p */
while (p->tot_len != p->len) {
/* make sure invariant condition holds */
LWIP_ASSERT("p->len < p->tot_len", p->len < p->tot_len);
/* make sure each packet is complete */
LWIP_ASSERT("p->next != NULL", p->next != NULL);
p = p->next;
}
/* { p->tot_len == p->len } => p is the last pbuf of the first packet */
/* remember next packet on queue in q */
q = p->next;
/* dequeue packet p from queue */
p->next = NULL;
/* any next packet on queue? */
if (q != NULL) {
/* although q is no longer referenced by p, it MUST be referenced by
* the caller, who is maintaining this packet queue. So, we do not call
* pbuf_free(q) here, resulting in an implicit pbuf_ref(q) for the caller. */
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_dequeue: first remaining packet on queue is %p\n", (void *)q));
} else {
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_dequeue: no further packets on queue\n"));
}
return q;
}
#endif
/**
*
* Create PBUF_POOL (or PBUF_RAM) copies of PBUF_REF pbufs.
*
* Used to queue packets on behalf of the lwIP stack, such as
* ARP based queueing.
*
* Go through a pbuf chain and replace any PBUF_REF buffers
* with PBUF_POOL (or PBUF_RAM) pbufs, each taking a copy of
* the referenced data.
*
* @note You MUST explicitly use p = pbuf_take(p);
* The pbuf you give as argument, may have been replaced
* by a (differently located) copy through pbuf_take()!
*
* @note Any replaced pbufs will be freed through pbuf_free().
* This may deallocate them if they become no longer referenced.
*
* @param p Head of pbuf chain to process
*
* @return Pointer to head of pbuf chain
*/
struct pbuf *
pbuf_take(struct pbuf *p)
{
struct pbuf *q , *prev, *head;
LWIP_ASSERT("pbuf_take: p != NULL\n", p != NULL);
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_take(%p)\n", (void*)p));
prev = NULL;
head = p;
/* iterate through pbuf chain */
do
{
/* pbuf is of type PBUF_REF? */
if (p->flags == PBUF_FLAG_REF) {
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE, ("pbuf_take: encountered PBUF_REF %p\n", (void *)p));
/* allocate a pbuf (w/ payload) fully in RAM */
/* PBUF_POOL buffers are faster if we can use them */
if (p->len <= PBUF_POOL_BUFSIZE) {
q = pbuf_alloc(PBUF_RAW, p->len, PBUF_POOL);
if (q == NULL) {
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_POOL\n"));
}
} else {
/* no replacement pbuf yet */
q = NULL;
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: PBUF_POOL too small to replace PBUF_REF\n"));
}
/* no (large enough) PBUF_POOL was available? retry with PBUF_RAM */
if (q == NULL) {
q = pbuf_alloc(PBUF_RAW, p->len, PBUF_RAM);
if (q == NULL) {
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_RAM\n"));
}
}
/* replacement pbuf could be allocated? */
if (q != NULL)
{
/* copy p to q */
/* copy successor */
q->next = p->next;
/* remove linkage from original pbuf */
p->next = NULL;
/* remove linkage to original pbuf */
if (prev != NULL) {
/* prev->next == p at this point */
LWIP_ASSERT("prev->next == p", prev->next == p);
/* break chain and insert new pbuf instead */
prev->next = q;
/* prev == NULL, so we replaced the head pbuf of the chain */
} else {
head = q;
}
/* copy pbuf payload */
memcpy(q->payload, p->payload, p->len);
q->tot_len = p->tot_len;
q->len = p->len;
/* in case p was the first pbuf, it is no longer refered to by
* our caller, as the caller MUST do p = pbuf_take(p);
* in case p was not the first pbuf, it is no longer refered to
* by prev. we can safely free the pbuf here.
* (note that we have set p->next to NULL already so that
* we will not free the rest of the chain by accident.)
*/
pbuf_free(p);
/* do not copy ref, since someone else might be using the old buffer */
LWIP_DEBUGF(PBUF_DEBUG, ("pbuf_take: replaced PBUF_REF %p with %p\n", (void *)p, (void *)q));
p = q;
} else {
/* deallocate chain */
pbuf_free(head);
LWIP_DEBUGF(PBUF_DEBUG | 2, ("pbuf_take: failed to allocate replacement pbuf for %p\n", (void *)p));
return NULL;
}
/* p->flags != PBUF_FLAG_REF */
} else {
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 1, ("pbuf_take: skipping pbuf not of type PBUF_REF\n"));
}
/* remember this pbuf */
prev = p;
/* proceed to next pbuf in original chain */
p = p->next;
} while (p);
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 1, ("pbuf_take: end of chain reached.\n"));
return head;
}
/**
* Dechains the first pbuf from its succeeding pbufs in the chain.
*
* Makes p->tot_len field equal to p->len.
* @param p pbuf to dechain
* @return remainder of the pbuf chain, or NULL if it was de-allocated.
* @note May not be called on a packet queue.
*/
struct pbuf *
pbuf_dechain(struct pbuf *p)
{
struct pbuf *q;
u8_t tail_gone = 1;
/* tail */
q = p->next;
/* pbuf has successor in chain? */
if (q != NULL) {
/* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */
LWIP_ASSERT("p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len);
/* enforce invariant if assertion is disabled */
q->tot_len = p->tot_len - p->len;
/* decouple pbuf from remainder */
p->next = NULL;
/* total length of pbuf p is its own length only */
p->tot_len = p->len;
/* q is no longer referenced by p, free it */
LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE, ("pbuf_dechain: unreferencing %p\n", (void *)q));
tail_gone = pbuf_free(q);
if (tail_gone > 0) {
LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE,
("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q));
}
/* return remaining tail or NULL if deallocated */
}
/* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */
LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len);
return (tail_gone > 0? NULL: q);
}

View File

@@ -0,0 +1,326 @@
/**
* @file
*
* Implementation of raw protocol PCBs for low-level handling of
* different types of protocols besides (or overriding) those
* already available in lwIP.
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#include <string.h>
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/memp.h"
#include "lwip/inet.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#include "lwip/raw.h"
#include "lwip/stats.h"
#include "arch/perf.h"
#include "lwip/snmp.h"
#if LWIP_RAW
/** The list of RAW PCBs */
static struct raw_pcb *raw_pcbs = NULL;
void
raw_init(void)
{
raw_pcbs = NULL;
}
/**
* Determine if in incoming IP packet is covered by a RAW PCB
* and if so, pass it to a user-provided receive callback function.
*
* Given an incoming IP datagram (as a chain of pbufs) this function
* finds a corresponding RAW PCB and calls the corresponding receive
* callback function.
*
* @param pbuf pbuf to be demultiplexed to a RAW PCB.
* @param netif network interface on which the datagram was received.
* @Return - 1 if the packet has been eaten by a RAW PCB receive
* callback function. The caller MAY NOT not reference the
* packet any longer, and MAY NOT call pbuf_free().
* @return - 0 if packet is not eaten (pbuf is still referenced by the
* caller).
*
*/
u8_t
raw_input(struct pbuf *p, struct netif *inp)
{
struct raw_pcb *pcb;
struct ip_hdr *iphdr;
s16_t proto;
u8_t eaten = 0;
iphdr = p->payload;
proto = IPH_PROTO(iphdr);
pcb = raw_pcbs;
/* loop through all raw pcbs until the packet is eaten by one */
/* this allows multiple pcbs to match against the packet by design */
while ((eaten == 0) && (pcb != NULL)) {
if (pcb->protocol == proto) {
/* receive callback function available? */
if (pcb->recv != NULL) {
/* the receive callback function did not eat the packet? */
if (pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src)) != 0)
{
/* receive function ate the packet */
p = NULL;
eaten = 1;
}
}
/* no receive callback function was set for this raw PCB */
/* drop the packet */
}
pcb = pcb->next;
}
return eaten;
}
/**
* Bind a RAW PCB.
*
* @param pcb RAW PCB to be bound with a local address ipaddr.
* @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to
* bind to all local interfaces.
*
* @return lwIP error code.
* - ERR_OK. Successful. No error occured.
* - ERR_USE. The specified IP address is already bound to by
* another RAW PCB.
*
* @see raw_disconnect()
*/
err_t
raw_bind(struct raw_pcb *pcb, struct ip_addr *ipaddr)
{
ip_addr_set(&pcb->local_ip, ipaddr);
return ERR_OK;
}
/**
* Connect an RAW PCB. This function is required by upper layers
* of lwip. Using the raw api you could use raw_sendto() instead
*
* This will associate the RAW PCB with the remote address.
*
* @param pcb RAW PCB to be connected with remote address ipaddr and port.
* @param ipaddr remote IP address to connect with.
*
* @return lwIP error code
*
* @see raw_disconnect() and raw_sendto()
*/
err_t
raw_connect(struct raw_pcb *pcb, struct ip_addr *ipaddr)
{
ip_addr_set(&pcb->remote_ip, ipaddr);
return ERR_OK;
}
/**
* Set the callback function for received packets that match the
* raw PCB's protocol and binding.
*
* The callback function MUST either
* - eat the packet by calling pbuf_free() and returning non-zero. The
* packet will not be passed to other raw PCBs or other protocol layers.
* - not free the packet, and return zero. The packet will be matched
* against further PCBs and/or forwarded to another protocol layers.
*
* @return non-zero if the packet was free()d, zero if the packet remains
* available for others.
*/
void
raw_recv(struct raw_pcb *pcb,
u8_t (* recv)(void *arg, struct raw_pcb *upcb, struct pbuf *p,
struct ip_addr *addr),
void *recv_arg)
{
/* remember recv() callback and user data */
pcb->recv = recv;
pcb->recv_arg = recv_arg;
}
/**
* Send the raw IP packet to the given address. Note that actually you cannot
* modify the IP headers (this is inconsistent with the receive callback where
* you actually get the IP headers), you can only specify the IP payload here.
* It requires some more changes in lwIP. (there will be a raw_send() function
* then.)
*
* @param pcb the raw pcb which to send
* @param p the IP payload to send
* @param ipaddr the destination address of the IP packet
*
*/
err_t
raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
{
err_t err;
struct netif *netif;
struct ip_addr *src_ip;
struct pbuf *q; /* q will be sent down the stack */
LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 3, ("raw_sendto\n"));
/* not enough space to add an IP header to first pbuf in given p chain? */
if (pbuf_header(p, IP_HLEN)) {
/* allocate header in new pbuf */
q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM);
/* new header pbuf could not be allocated? */
if (q == NULL) {
LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 2, ("raw_sendto: could not allocate header\n"));
return ERR_MEM;
}
/* chain header q in front of given pbuf p */
pbuf_chain(q, p);
/* { first pbuf q points to header pbuf } */
LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
} else {
/* first pbuf q equals given pbuf */
q = p;
pbuf_header(q, -IP_HLEN);
}
if ((netif = ip_route(ipaddr)) == NULL) {
LWIP_DEBUGF(RAW_DEBUG | 1, ("raw_sendto: No route to 0x%"X32_F"\n", ipaddr->addr));
#if RAW_STATS
/* ++lwip_stats.raw.rterr;*/
#endif /* RAW_STATS */
/* free any temporary header pbuf allocated by pbuf_header() */
if (q != p) {
pbuf_free(q);
}
return ERR_RTE;
}
if (ip_addr_isany(&pcb->local_ip)) {
/* use outgoing network interface IP address as source address */
src_ip = &(netif->ip_addr);
} else {
/* use RAW PCB local IP address as source address */
src_ip = &(pcb->local_ip);
}
err = ip_output_if (q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif);
/* did we chain a header earlier? */
if (q != p) {
/* free the header */
pbuf_free(q);
}
return err;
}
/**
* Send the raw IP packet to the address given by raw_connect()
*
* @param pcb the raw pcb which to send
* @param p the IP payload to send
* @param ipaddr the destination address of the IP packet
*
*/
err_t
raw_send(struct raw_pcb *pcb, struct pbuf *p)
{
return raw_sendto(pcb, p, &pcb->remote_ip);
}
/**
* Remove an RAW PCB.
*
* @param pcb RAW PCB to be removed. The PCB is removed from the list of
* RAW PCB's and the data structure is freed from memory.
*
* @see raw_new()
*/
void
raw_remove(struct raw_pcb *pcb)
{
struct raw_pcb *pcb2;
/* pcb to be removed is first in list? */
if (raw_pcbs == pcb) {
/* make list start at 2nd pcb */
raw_pcbs = raw_pcbs->next;
/* pcb not 1st in list */
} else for(pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
/* find pcb in raw_pcbs list */
if (pcb2->next != NULL && pcb2->next == pcb) {
/* remove pcb from list */
pcb2->next = pcb->next;
}
}
memp_free(MEMP_RAW_PCB, pcb);
}
/**
* Create a RAW PCB.
*
* @return The RAW PCB which was created. NULL if the PCB data structure
* could not be allocated.
*
* @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP)
*
* @see raw_remove()
*/
struct raw_pcb *
raw_new(u16_t proto) {
struct raw_pcb *pcb;
LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 3, ("raw_new\n"));
pcb = memp_malloc(MEMP_RAW_PCB);
/* could allocate RAW PCB? */
if (pcb != NULL) {
/* initialize PCB to all zeroes */
memset(pcb, 0, sizeof(struct raw_pcb));
pcb->protocol = proto;
pcb->ttl = RAW_TTL;
pcb->next = raw_pcbs;
raw_pcbs = pcb;
}
return pcb;
}
#endif /* LWIP_RAW */

View File

@@ -0,0 +1,115 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#include <string.h>
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/stats.h"
#include "lwip/mem.h"
#if LWIP_STATS
struct stats_ lwip_stats;
void
stats_init(void)
{
memset(&lwip_stats, 0, sizeof(struct stats_));
}
#if LWIP_STATS_DISPLAY
void
stats_display_proto(struct stats_proto *proto, char *name)
{
LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
LWIP_PLATFORM_DIAG(("xmit: %"S16_F"\n\t", proto->xmit));
LWIP_PLATFORM_DIAG(("rexmit: %"S16_F"\n\t", proto->rexmit));
LWIP_PLATFORM_DIAG(("recv: %"S16_F"\n\t", proto->recv));
LWIP_PLATFORM_DIAG(("fw: %"S16_F"\n\t", proto->fw));
LWIP_PLATFORM_DIAG(("drop: %"S16_F"\n\t", proto->drop));
LWIP_PLATFORM_DIAG(("chkerr: %"S16_F"\n\t", proto->chkerr));
LWIP_PLATFORM_DIAG(("lenerr: %"S16_F"\n\t", proto->lenerr));
LWIP_PLATFORM_DIAG(("memerr: %"S16_F"\n\t", proto->memerr));
LWIP_PLATFORM_DIAG(("rterr: %"S16_F"\n\t", proto->rterr));
LWIP_PLATFORM_DIAG(("proterr: %"S16_F"\n\t", proto->proterr));
LWIP_PLATFORM_DIAG(("opterr: %"S16_F"\n\t", proto->opterr));
LWIP_PLATFORM_DIAG(("err: %"S16_F"\n\t", proto->err));
LWIP_PLATFORM_DIAG(("cachehit: %"S16_F"\n", proto->cachehit));
}
void
stats_display_pbuf(struct stats_pbuf *pbuf)
{
LWIP_PLATFORM_DIAG(("\nPBUF\n\t"));
LWIP_PLATFORM_DIAG(("avail: %"S16_F"\n\t", pbuf->avail));
LWIP_PLATFORM_DIAG(("used: %"S16_F"\n\t", pbuf->used));
LWIP_PLATFORM_DIAG(("max: %"S16_F"\n\t", pbuf->max));
LWIP_PLATFORM_DIAG(("err: %"S16_F"\n\t", pbuf->err));
LWIP_PLATFORM_DIAG(("alloc_locked: %"S16_F"\n\t", pbuf->alloc_locked));
LWIP_PLATFORM_DIAG(("refresh_locked: %"S16_F"\n", pbuf->refresh_locked));
}
void
stats_display_mem(struct stats_mem *mem, char *name)
{
LWIP_PLATFORM_DIAG(("\n MEM %s\n\t", name));
LWIP_PLATFORM_DIAG(("avail: %"S16_F"\n\t", mem->avail));
LWIP_PLATFORM_DIAG(("used: %"S16_F"\n\t", mem->used));
LWIP_PLATFORM_DIAG(("max: %"S16_F"\n\t", mem->max));
LWIP_PLATFORM_DIAG(("err: %"S16_F"\n", mem->err));
}
void
stats_display(void)
{
s16_t i;
char * memp_names[] = {"PBUF", "RAW_PCB", "UDP_PCB", "TCP_PCB", "TCP_PCB_LISTEN",
"TCP_SEG", "NETBUF", "NETCONN", "API_MSG", "TCP_MSG", "TIMEOUT"};
stats_display_proto(&lwip_stats.link, "LINK");
stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG");
stats_display_proto(&lwip_stats.ip, "IP");
stats_display_proto(&lwip_stats.icmp, "ICMP");
stats_display_proto(&lwip_stats.udp, "UDP");
stats_display_proto(&lwip_stats.tcp, "TCP");
stats_display_pbuf(&lwip_stats.pbuf);
stats_display_mem(&lwip_stats.mem, "HEAP");
for (i = 0; i < MEMP_MAX; i++) {
stats_display_mem(&lwip_stats.memp[i], memp_names[i]);
}
}
#endif /* LWIP_STATS_DISPLAY */
#endif /* LWIP_STATS */

View File

@@ -0,0 +1,294 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/sys.h"
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/memp.h"
#if (NO_SYS == 0)
struct sswt_cb
{
s16_t timeflag;
sys_sem_t *psem;
};
void
sys_mbox_fetch(sys_mbox_t mbox, void **msg)
{
u32_t time;
struct sys_timeouts *timeouts;
struct sys_timeout *tmptimeout;
sys_timeout_handler h;
void *arg;
again:
timeouts = sys_arch_timeouts();
if (!timeouts || !timeouts->next) {
sys_arch_mbox_fetch(mbox, msg, 0);
} else {
if (timeouts->next->time > 0) {
time = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time);
} else {
time = SYS_ARCH_TIMEOUT;
}
if (time == SYS_ARCH_TIMEOUT) {
/* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
could be fetched. We should now call the timeout handler and
deallocate the memory allocated for the timeout. */
tmptimeout = timeouts->next;
timeouts->next = tmptimeout->next;
h = tmptimeout->h;
arg = tmptimeout->arg;
memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
if (h != NULL) {
LWIP_DEBUGF(SYS_DEBUG, ("smf calling h=%p(%p)\n", (void *)h, (void *)arg));
h(arg);
}
/* We try again to fetch a message from the mbox. */
goto again;
} else {
/* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
occured. The time variable is set to the number of
milliseconds we waited for the message. */
if (time <= timeouts->next->time) {
timeouts->next->time -= time;
} else {
timeouts->next->time = 0;
}
}
}
}
void
sys_sem_wait(sys_sem_t sem)
{
u32_t time;
struct sys_timeouts *timeouts;
struct sys_timeout *tmptimeout;
sys_timeout_handler h;
void *arg;
/* while (sys_arch_sem_wait(sem, 1000) == 0);
return;*/
again:
timeouts = sys_arch_timeouts();
if (!timeouts || !timeouts->next) {
sys_arch_sem_wait(sem, 0);
} else {
if (timeouts->next->time > 0) {
time = sys_arch_sem_wait(sem, timeouts->next->time);
} else {
time = SYS_ARCH_TIMEOUT;
}
if (time == SYS_ARCH_TIMEOUT) {
/* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
could be fetched. We should now call the timeout handler and
deallocate the memory allocated for the timeout. */
tmptimeout = timeouts->next;
timeouts->next = tmptimeout->next;
h = tmptimeout->h;
arg = tmptimeout->arg;
memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
if (h != NULL) {
LWIP_DEBUGF(SYS_DEBUG, ("ssw h=%p(%p)\n", (void *)h, (void *)arg));
h(arg);
}
/* We try again to fetch a message from the mbox. */
goto again;
} else {
/* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
occured. The time variable is set to the number of
milliseconds we waited for the message. */
if (time <= timeouts->next->time) {
timeouts->next->time -= time;
} else {
timeouts->next->time = 0;
}
}
}
}
void
sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
{
struct sys_timeouts *timeouts;
struct sys_timeout *timeout, *t;
timeout = memp_malloc(MEMP_SYS_TIMEOUT);
if (timeout == NULL) {
return;
}
timeout->next = NULL;
timeout->h = h;
timeout->arg = arg;
timeout->time = msecs;
timeouts = sys_arch_timeouts();
LWIP_DEBUGF(SYS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" h=%p arg=%p\n",
(void *)timeout, msecs, (void *)h, (void *)arg));
LWIP_ASSERT("sys_timeout: timeouts != NULL", timeouts != NULL);
if (timeouts->next == NULL) {
timeouts->next = timeout;
return;
}
if (timeouts->next->time > msecs) {
timeouts->next->time -= msecs;
timeout->next = timeouts->next;
timeouts->next = timeout;
} else {
for(t = timeouts->next; t != NULL; t = t->next) {
timeout->time -= t->time;
if (t->next == NULL || t->next->time > timeout->time) {
if (t->next != NULL) {
t->next->time -= timeout->time;
}
timeout->next = t->next;
t->next = timeout;
break;
}
}
}
}
/* Go through timeout list (for this task only) and remove the first matching entry,
even though the timeout has not triggered yet.
*/
void
sys_untimeout(sys_timeout_handler h, void *arg)
{
struct sys_timeouts *timeouts;
struct sys_timeout *prev_t, *t;
timeouts = sys_arch_timeouts();
if (timeouts->next == NULL)
return;
for (t = timeouts->next, prev_t = NULL; t != NULL; prev_t = t, t = t->next)
{
if ((t->h == h) && (t->arg == arg))
{
/* We have a match */
/* Unlink from previous in list */
if (prev_t == NULL)
timeouts->next = t->next;
else
prev_t->next = t->next;
/* If not the last one, add time of this one back to next */
if (t->next != NULL)
t->next->time += t->time;
memp_free(MEMP_SYS_TIMEOUT, t);
return;
}
}
return;
}
static void
sswt_handler(void *arg)
{
struct sswt_cb *sswt_cb = (struct sswt_cb *) arg;
/* Timeout. Set flag to TRUE and signal semaphore */
sswt_cb->timeflag = 1;
sys_sem_signal(*(sswt_cb->psem));
}
/* Wait for a semaphore with timeout (specified in ms) */
/* timeout = 0: wait forever */
/* Returns 0 on timeout. 1 otherwise */
int
sys_sem_wait_timeout(sys_sem_t sem, u32_t timeout)
{
struct sswt_cb sswt_cb;
sswt_cb.psem = &sem;
sswt_cb.timeflag = 0;
/* If timeout is zero, then just wait forever */
if (timeout > 0)
/* Create a timer and pass it the address of our flag */
sys_timeout(timeout, sswt_handler, &sswt_cb);
sys_sem_wait(sem);
/* Was it a timeout? */
if (sswt_cb.timeflag)
{
/* timeout */
return 0;
} else {
/* Not a timeout. Remove timeout entry */
sys_untimeout(sswt_handler, &sswt_cb);
return 1;
}
}
void
sys_msleep(u32_t ms)
{
sys_sem_t delaysem = sys_sem_new(0);
sys_sem_wait_timeout(delaysem, ms);
sys_sem_free(delaysem);
}
#endif /* NO_SYS */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,721 @@
/**
* @file
*
* Transmission Control Protocol, outgoing traffic
*
* The output functions of TCP.
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#include <string.h>
#include "lwip/def.h"
#include "lwip/opt.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/sys.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#include "lwip/inet.h"
#include "lwip/tcp.h"
#include "lwip/stats.h"
#if LWIP_TCP
/* Forward declarations.*/
static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
err_t
tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
{
/* no data, no length, flags, copy=1, no optdata, no optdatalen */
return tcp_enqueue(pcb, NULL, 0, flags, 1, NULL, 0);
}
/**
* Write data for sending (but does not send it immediately).
*
* It waits in the expectation of more data being sent soon (as
* it can send them more efficiently by combining them together).
* To prompt the system to send data now, call tcp_output() after
* calling tcp_write().
*
* @arg pcb Protocol control block of the TCP connection to enqueue data for.
*
* @see tcp_write()
*/
err_t
tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
{
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%"U16_F", copy=%"U16_F")\n", (void *)pcb,
arg, len, (u16_t)copy));
/* connection is in valid state for data transmission? */
if (pcb->state == ESTABLISHED ||
pcb->state == CLOSE_WAIT ||
pcb->state == SYN_SENT ||
pcb->state == SYN_RCVD) {
if (len > 0) {
return tcp_enqueue(pcb, (void *)arg, len, 0, copy, NULL, 0);
}
return ERR_OK;
} else {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_STATE | 3, ("tcp_write() called in invalid state\n"));
return ERR_CONN;
}
}
/**
* Enqueue either data or TCP options (but not both) for tranmission
*
*
*
* @arg pcb Protocol control block for the TCP connection to enqueue data for.
* @arg arg Pointer to the data to be enqueued for sending.
* @arg len Data length in bytes
* @arg flags
* @arg copy 1 if data must be copied, 0 if data is non-volatile and can be
* referenced.
* @arg optdata
* @arg optlen
*/
err_t
tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
u8_t flags, u8_t copy,
u8_t *optdata, u8_t optlen)
{
struct pbuf *p;
struct tcp_seg *seg, *useg, *queue;
u32_t left, seqno;
u16_t seglen;
void *ptr;
u8_t queuelen;
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue(pcb=%p, arg=%p, len=%"U16_F", flags=%"X16_F", copy=%"U16_F")\n",
(void *)pcb, arg, len, (u16_t)flags, (u16_t)copy));
LWIP_ASSERT("tcp_enqueue: len == 0 || optlen == 0 (programmer violates API)",
len == 0 || optlen == 0);
LWIP_ASSERT("tcp_enqueue: arg == NULL || optdata == NULL (programmer violates API)",
arg == NULL || optdata == NULL);
/* fail on too much data */
if (len > pcb->snd_buf) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", len, pcb->snd_buf));
return ERR_MEM;
}
left = len;
ptr = arg;
/* seqno will be the sequence number of the first segment enqueued
* by the call to this function. */
seqno = pcb->snd_lbb;
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
/* If total number of pbufs on the unsent/unacked queues exceeds the
* configured maximum, return an error */
queuelen = pcb->snd_queuelen;
if (queuelen >= TCP_SND_QUEUELEN) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too long queue %"U16_F" (max %"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
TCP_STATS_INC(tcp.memerr);
return ERR_MEM;
}
if (queuelen != 0) {
LWIP_ASSERT("tcp_enqueue: pbufs on queue => at least one queue non-empty",
pcb->unacked != NULL || pcb->unsent != NULL);
} else {
LWIP_ASSERT("tcp_enqueue: no pbufs on queue => both queues empty",
pcb->unacked == NULL && pcb->unsent == NULL);
}
/* First, break up the data into segments and tuck them together in
* the local "queue" variable. */
useg = queue = seg = NULL;
seglen = 0;
while (queue == NULL || left > 0) {
/* The segment length should be the MSS if the data to be enqueued
* is larger than the MSS. */
seglen = left > pcb->mss? pcb->mss: left;
/* Allocate memory for tcp_seg, and fill in fields. */
seg = memp_malloc(MEMP_TCP_SEG);
if (seg == NULL) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for tcp_seg\n"));
goto memerr;
}
seg->next = NULL;
seg->p = NULL;
/* first segment of to-be-queued data? */
if (queue == NULL) {
queue = seg;
}
/* subsequent segments of to-be-queued data */
else {
/* Attach the segment to the end of the queued segments */
LWIP_ASSERT("useg != NULL", useg != NULL);
useg->next = seg;
}
/* remember last segment of to-be-queued data for next iteration */
useg = seg;
/* If copy is set, memory should be allocated
* and data copied into pbuf, otherwise data comes from
* ROM or other static memory, and need not be copied. If
* optdata is != NULL, we have options instead of data. */
/* options? */
if (optdata != NULL) {
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
goto memerr;
}
++queuelen;
seg->dataptr = seg->p->payload;
}
/* copy from volatile memory? */
else if (copy) {
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_RAM)) == NULL) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue : could not allocate memory for pbuf copy size %"U16_F"\n", seglen));
goto memerr;
}
++queuelen;
if (arg != NULL) {
memcpy(seg->p->payload, ptr, seglen);
}
seg->dataptr = seg->p->payload;
}
/* do not copy data */
else {
/* First, allocate a pbuf for holding the data.
* since the referenced data is available at least until it is sent out on the
* link (as it has to be ACKed by the remote party) we can safely use PBUF_ROM
* instead of PBUF_REF here.
*/
if ((p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for zero-copy pbuf\n"));
goto memerr;
}
++queuelen;
/* reference the non-volatile payload data */
p->payload = ptr;
seg->dataptr = ptr;
/* Second, allocate a pbuf for the headers. */
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_RAM)) == NULL) {
/* If allocation fails, we have to deallocate the data pbuf as
* well. */
pbuf_free(p);
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for header pbuf\n"));
goto memerr;
}
++queuelen;
/* Concatenate the headers and data pbufs together. */
pbuf_cat(seg->p/*header*/, p/*data*/);
p = NULL;
}
/* Now that there are more segments queued, we check again if the
length of the queue exceeds the configured maximum. */
if (queuelen > TCP_SND_QUEUELEN) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
goto memerr;
}
seg->len = seglen;
/* build TCP header */
if (pbuf_header(seg->p, TCP_HLEN)) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
TCP_STATS_INC(tcp.err);
goto memerr;
}
seg->tcphdr = seg->p->payload;
seg->tcphdr->src = htons(pcb->local_port);
seg->tcphdr->dest = htons(pcb->remote_port);
seg->tcphdr->seqno = htonl(seqno);
seg->tcphdr->urgp = 0;
TCPH_FLAGS_SET(seg->tcphdr, flags);
/* don't fill in tcphdr->ackno and tcphdr->wnd until later */
/* Copy the options into the header, if they are present. */
if (optdata == NULL) {
TCPH_HDRLEN_SET(seg->tcphdr, 5);
}
else {
TCPH_HDRLEN_SET(seg->tcphdr, (5 + optlen / 4));
/* Copy options into data portion of segment.
Options can thus only be sent in non data carrying
segments such as SYN|ACK. */
memcpy(seg->dataptr, optdata, optlen);
}
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE, ("tcp_enqueue: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n",
ntohl(seg->tcphdr->seqno),
ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
(u16_t)flags));
left -= seglen;
seqno += seglen;
ptr = (void *)((u8_t *)ptr + seglen);
}
/* Now that the data to be enqueued has been broken up into TCP
segments in the queue variable, we add them to the end of the
pcb->unsent queue. */
if (pcb->unsent == NULL) {
useg = NULL;
}
else {
for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
}
/* { useg is last segment on the unsent queue, NULL if list is empty } */
/* If there is room in the last pbuf on the unsent queue,
chain the first pbuf on the queue together with that. */
if (useg != NULL &&
TCP_TCPLEN(useg) != 0 &&
!(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
!(flags & (TCP_SYN | TCP_FIN)) &&
/* fit within max seg size */
useg->len + queue->len <= pcb->mss) {
/* Remove TCP header from first segment of our to-be-queued list */
pbuf_header(queue->p, -TCP_HLEN);
pbuf_cat(useg->p, queue->p);
useg->len += queue->len;
useg->next = queue->next;
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE | DBG_STATE, ("tcp_enqueue: chaining segments, new len %"U16_F"\n", useg->len));
if (seg == queue) {
seg = NULL;
}
memp_free(MEMP_TCP_SEG, queue);
}
else {
/* empty list */
if (useg == NULL) {
/* initialize list with this segment */
pcb->unsent = queue;
}
/* enqueue segment */
else {
useg->next = queue;
}
}
if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
++len;
}
pcb->snd_lbb += len;
pcb->snd_buf -= len;
/* update number of segments on the queues */
pcb->snd_queuelen = queuelen;
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %"S16_F" (after enqueued)\n", pcb->snd_queuelen));
if (pcb->snd_queuelen != 0) {
LWIP_ASSERT("tcp_enqueue: valid queue length",
pcb->unacked != NULL || pcb->unsent != NULL);
}
/* Set the PSH flag in the last segment that we enqueued, but only
if the segment has data (indicated by seglen > 0). */
if (seg != NULL && seglen > 0 && seg->tcphdr != NULL) {
TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
}
return ERR_OK;
memerr:
TCP_STATS_INC(tcp.memerr);
if (queue != NULL) {
tcp_segs_free(queue);
}
if (pcb->snd_queuelen != 0) {
LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
pcb->unsent != NULL);
}
LWIP_DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_enqueue: %"S16_F" (with mem err)\n", pcb->snd_queuelen));
return ERR_MEM;
}
/* find out what we can send and send it */
err_t
tcp_output(struct tcp_pcb *pcb)
{
struct pbuf *p;
struct tcp_hdr *tcphdr;
struct tcp_seg *seg, *useg;
u32_t wnd;
#if TCP_CWND_DEBUG
s16_t i = 0;
#endif /* TCP_CWND_DEBUG */
/* First, check if we are invoked by the TCP input processing
code. If so, we do not output anything. Instead, we rely on the
input processing code to call us when input processing is done
with. */
if (tcp_input_pcb == pcb) {
return ERR_OK;
}
wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
seg = pcb->unsent;
/* useg should point to last segment on unacked queue */
useg = pcb->unacked;
if (useg != NULL) {
for (; useg->next != NULL; useg = useg->next);
}
/* If the TF_ACK_NOW flag is set and no data will be sent (either
* because the ->unsent queue is empty or because the window does
* not allow it), construct an empty ACK segment and send it.
*
* If data is to be sent, we will just piggyback the ACK (see below).
*/
if (pcb->flags & TF_ACK_NOW &&
(seg == NULL ||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
if (p == NULL) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
return ERR_BUF;
}
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));
/* remove ACK flags from the PCB, as we send an empty ACK now */
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
tcphdr = p->payload;
tcphdr->src = htons(pcb->local_port);
tcphdr->dest = htons(pcb->remote_port);
tcphdr->seqno = htonl(pcb->snd_nxt);
tcphdr->ackno = htonl(pcb->rcv_nxt);
TCPH_FLAGS_SET(tcphdr, TCP_ACK);
tcphdr->wnd = htons(pcb->rcv_wnd);
tcphdr->urgp = 0;
TCPH_HDRLEN_SET(tcphdr, 5);
tcphdr->chksum = 0;
#if CHECKSUM_GEN_TCP
tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
IP_PROTO_TCP, p->tot_len);
#endif
ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
IP_PROTO_TCP);
pbuf_free(p);
return ERR_OK;
}
#if TCP_OUTPUT_DEBUG
if (seg == NULL) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", (void*)pcb->unsent));
}
#endif /* TCP_OUTPUT_DEBUG */
#if TCP_CWND_DEBUG
if (seg == NULL) {
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", seg == NULL, ack %"U32_F"\n",
pcb->snd_wnd, pcb->cwnd, wnd,
pcb->lastack));
} else {
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n",
pcb->snd_wnd, pcb->cwnd, wnd,
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
ntohl(seg->tcphdr->seqno), pcb->lastack));
}
#endif /* TCP_CWND_DEBUG */
/* data available and window allows it to be sent? */
while (seg != NULL &&
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
#if TCP_CWND_DEBUG
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n",
pcb->snd_wnd, pcb->cwnd, wnd,
ntohl(seg->tcphdr->seqno) + seg->len -
pcb->lastack,
ntohl(seg->tcphdr->seqno), pcb->lastack, i));
++i;
#endif /* TCP_CWND_DEBUG */
pcb->unsent = seg->next;
if (pcb->state != SYN_SENT) {
TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
}
tcp_output_segment(seg, pcb);
pcb->snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
if (TCP_SEQ_LT(pcb->snd_max, pcb->snd_nxt)) {
pcb->snd_max = pcb->snd_nxt;
}
/* put segment on unacknowledged list if length > 0 */
if (TCP_TCPLEN(seg) > 0) {
seg->next = NULL;
/* unacked list is empty? */
if (pcb->unacked == NULL) {
pcb->unacked = seg;
useg = seg;
/* unacked list is not empty? */
} else {
/* In the case of fast retransmit, the packet should not go to the tail
* of the unacked queue, but rather at the head. We need to check for
* this case. -STJ Jul 27, 2004 */
if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))){
/* add segment to head of unacked list */
seg->next = pcb->unacked;
pcb->unacked = seg;
} else {
/* add segment to tail of unacked list */
useg->next = seg;
useg = useg->next;
}
}
/* do not queue empty segments on the unacked list */
} else {
tcp_seg_free(seg);
}
seg = pcb->unsent;
}
return ERR_OK;
}
/**
* Actually send a TCP segment over IP
*/
static void
tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
{
u16_t len;
struct netif *netif;
/* The TCP header has already been constructed, but the ackno and
wnd fields remain. */
seg->tcphdr->ackno = htonl(pcb->rcv_nxt);
/* silly window avoidance */
if (pcb->rcv_wnd < pcb->mss) {
seg->tcphdr->wnd = 0;
} else {
/* advertise our receive window size in this TCP segment */
seg->tcphdr->wnd = htons(pcb->rcv_wnd);
}
/* If we don't have a local IP address, we get one by
calling ip_route(). */
if (ip_addr_isany(&(pcb->local_ip))) {
netif = ip_route(&(pcb->remote_ip));
if (netif == NULL) {
return;
}
ip_addr_set(&(pcb->local_ip), &(netif->ip_addr));
}
pcb->rtime = 0;
if (pcb->rttest == 0) {
pcb->rttest = tcp_ticks;
pcb->rtseq = ntohl(seg->tcphdr->seqno);
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq));
}
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n",
htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +
seg->len));
len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);
seg->p->len -= len;
seg->p->tot_len -= len;
seg->p->payload = seg->tcphdr;
seg->tcphdr->chksum = 0;
#if CHECKSUM_GEN_TCP
seg->tcphdr->chksum = inet_chksum_pseudo(seg->p,
&(pcb->local_ip),
&(pcb->remote_ip),
IP_PROTO_TCP, seg->p->tot_len);
#endif
TCP_STATS_INC(tcp.xmit);
ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
IP_PROTO_TCP);
}
void
tcp_rst(u32_t seqno, u32_t ackno,
struct ip_addr *local_ip, struct ip_addr *remote_ip,
u16_t local_port, u16_t remote_port)
{
struct pbuf *p;
struct tcp_hdr *tcphdr;
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
if (p == NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));
return;
}
tcphdr = p->payload;
tcphdr->src = htons(local_port);
tcphdr->dest = htons(remote_port);
tcphdr->seqno = htonl(seqno);
tcphdr->ackno = htonl(ackno);
TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK);
tcphdr->wnd = htons(TCP_WND);
tcphdr->urgp = 0;
TCPH_HDRLEN_SET(tcphdr, 5);
tcphdr->chksum = 0;
#if CHECKSUM_GEN_TCP
tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
IP_PROTO_TCP, p->tot_len);
#endif
TCP_STATS_INC(tcp.xmit);
/* Send output with hardcoded TTL since we have no access to the pcb */
ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
pbuf_free(p);
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno));
}
/* requeue all unacked segments for retransmission */
void
tcp_rexmit_rto(struct tcp_pcb *pcb)
{
struct tcp_seg *seg;
if (pcb->unacked == NULL) {
return;
}
/* Move all unacked segments to the head of the unsent queue */
for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
/* concatenate unsent queue after unacked queue */
seg->next = pcb->unsent;
/* unsent queue is the concatenated queue (of unacked, unsent) */
pcb->unsent = pcb->unacked;
/* unacked queue is now empty */
pcb->unacked = NULL;
pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
/* increment number of retransmissions */
++pcb->nrtx;
/* Don't take any RTT measurements after retransmitting. */
pcb->rttest = 0;
/* Do the actual retransmission */
tcp_output(pcb);
}
void
tcp_rexmit(struct tcp_pcb *pcb)
{
struct tcp_seg *seg;
if (pcb->unacked == NULL) {
return;
}
/* Move the first unacked segment to the unsent queue */
seg = pcb->unacked->next;
pcb->unacked->next = pcb->unsent;
pcb->unsent = pcb->unacked;
pcb->unacked = seg;
pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
++pcb->nrtx;
/* Don't take any rtt measurements after retransmitting. */
pcb->rttest = 0;
/* Do the actual retransmission. */
tcp_output(pcb);
}
void
tcp_keepalive(struct tcp_pcb *pcb)
{
struct pbuf *p;
struct tcp_hdr *tcphdr;
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt %"U16_F"\n", tcp_ticks, pcb->tmr, pcb->keep_cnt));
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
if(p == NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: could not allocate memory for pbuf\n"));
return;
}
tcphdr = p->payload;
tcphdr->src = htons(pcb->local_port);
tcphdr->dest = htons(pcb->remote_port);
tcphdr->seqno = htonl(pcb->snd_nxt - 1);
tcphdr->ackno = htonl(pcb->rcv_nxt);
tcphdr->wnd = htons(pcb->rcv_wnd);
tcphdr->urgp = 0;
TCPH_HDRLEN_SET(tcphdr, 5);
tcphdr->chksum = 0;
#if CHECKSUM_GEN_TCP
tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, IP_PROTO_TCP, p->tot_len);
#endif
TCP_STATS_INC(tcp.xmit);
/* Send output to IP */
ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
pbuf_free(p);
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n", pcb->snd_nxt - 1, pcb->rcv_nxt));
}
#endif /* LWIP_TCP */

View File

@@ -0,0 +1,655 @@
/**
* @file
* User Datagram Protocol module
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
/* udp.c
*
* The code for the User Datagram Protocol UDP.
*
*/
#include <string.h>
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/memp.h"
#include "lwip/inet.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#include "lwip/udp.h"
#include "lwip/icmp.h"
#include "lwip/stats.h"
#include "arch/perf.h"
#include "lwip/snmp.h"
/* The list of UDP PCBs */
#if LWIP_UDP
/* was static, but we may want to access this from a socket layer */
struct udp_pcb *udp_pcbs = NULL;
static struct udp_pcb *pcb_cache = NULL;
void
udp_init(void)
{
udp_pcbs = pcb_cache = NULL;
}
/**
* Process an incoming UDP datagram.
*
* Given an incoming UDP datagram (as a chain of pbufs) this function
* finds a corresponding UDP PCB and
*
* @param pbuf pbuf to be demultiplexed to a UDP PCB.
* @param netif network interface on which the datagram was received.
*
*/
void
udp_input(struct pbuf *p, struct netif *inp)
{
struct udp_hdr *udphdr;
struct udp_pcb *pcb;
struct udp_pcb *uncon_pcb;
struct ip_hdr *iphdr;
u16_t src, dest;
u8_t local_match;
PERF_START;
UDP_STATS_INC(udp.recv);
iphdr = p->payload;
if (pbuf_header(p, -((s16_t)(UDP_HLEN + IPH_HL(iphdr) * 4)))) {
/* drop short packets */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len));
UDP_STATS_INC(udp.lenerr);
UDP_STATS_INC(udp.drop);
snmp_inc_udpinerrors();
pbuf_free(p);
goto end;
}
udphdr = (struct udp_hdr *)((u8_t *)p->payload - UDP_HLEN);
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len));
src = ntohs(udphdr->src);
dest = ntohs(udphdr->dest);
udp_debug_print(udphdr);
/* print the UDP source and destination */
LWIP_DEBUGF(UDP_DEBUG, ("udp (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") <-- (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n",
ip4_addr1(&iphdr->dest), ip4_addr2(&iphdr->dest),
ip4_addr3(&iphdr->dest), ip4_addr4(&iphdr->dest), ntohs(udphdr->dest),
ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src),
ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), ntohs(udphdr->src)));
local_match = 0;
uncon_pcb = NULL;
/* Iterate through the UDP pcb list for a matching pcb */
for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
/* print the PCB local and remote address */
LWIP_DEBUGF(UDP_DEBUG, ("pcb (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") --- (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n",
ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port));
/* compare PCB local addr+port to UDP destination addr+port */
if ((pcb->local_port == dest) &&
(ip_addr_isany(&pcb->local_ip) ||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
local_match = 1;
if ((uncon_pcb == NULL) &&
((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) {
/* the first unconnected matching PCB */
uncon_pcb = pcb;
}
}
/* compare PCB remote addr+port to UDP source addr+port */
if ((local_match != 0) &&
(pcb->remote_port == src) &&
(ip_addr_isany(&pcb->remote_ip) ||
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)))) {
/* the first fully matching PCB */
break;
}
}
/* no fully matching pcb found? then look for an unconnected pcb */
if (pcb == NULL) {
pcb = uncon_pcb;
}
/* Check checksum if this is a match or if it was directed at us. */
if (pcb != NULL || ip_addr_cmp(&inp->ip_addr, &iphdr->dest))
{
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: calculating checksum\n"));
pbuf_header(p, UDP_HLEN);
#ifdef IPv6
if (iphdr->nexthdr == IP_PROTO_UDPLITE) {
#else
if (IPH_PROTO(iphdr) == IP_PROTO_UDPLITE) {
#endif /* IPv4 */
/* Do the UDP Lite checksum */
#if CHECKSUM_CHECK_UDP
if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
(struct ip_addr *)&(iphdr->dest),
IP_PROTO_UDPLITE, ntohs(udphdr->len)) != 0) {
LWIP_DEBUGF(UDP_DEBUG | 2, ("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
UDP_STATS_INC(udp.chkerr);
UDP_STATS_INC(udp.drop);
snmp_inc_udpinerrors();
pbuf_free(p);
goto end;
}
#endif
} else {
#if CHECKSUM_CHECK_UDP
if (udphdr->chksum != 0) {
if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
(struct ip_addr *)&(iphdr->dest),
IP_PROTO_UDP, p->tot_len) != 0) {
LWIP_DEBUGF(UDP_DEBUG | 2, ("udp_input: UDP datagram discarded due to failing checksum\n"));
UDP_STATS_INC(udp.chkerr);
UDP_STATS_INC(udp.drop);
snmp_inc_udpinerrors();
pbuf_free(p);
goto end;
}
}
#endif
}
pbuf_header(p, -UDP_HLEN);
if (pcb != NULL) {
snmp_inc_udpindatagrams();
/* callback */
if (pcb->recv != NULL)
{
pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src);
}
} else {
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: not for us.\n"));
/* No match was found, send ICMP destination port unreachable unless
destination address was broadcast/multicast. */
if (!ip_addr_isbroadcast(&iphdr->dest, inp) &&
!ip_addr_ismulticast(&iphdr->dest)) {
/* adjust pbuf pointer */
p->payload = iphdr;
icmp_dest_unreach(p, ICMP_DUR_PORT);
}
UDP_STATS_INC(udp.proterr);
UDP_STATS_INC(udp.drop);
snmp_inc_udpnoports();
pbuf_free(p);
}
} else {
pbuf_free(p);
}
end:
PERF_STOP("udp_input");
}
/**
* Send data to a specified address using UDP.
*
* @param pcb UDP PCB used to send the data.
* @param pbuf chain of pbuf's to be sent.
* @param dst_ip Destination IP address.
* @param dst_port Destination UDP port.
*
* If the PCB already has a remote address association, it will
* be restored after the data is sent.
*
* @return lwIP error code.
* - ERR_OK. Successful. No error occured.
* - ERR_MEM. Out of memory.
* - ERR_RTE. Could not find route to destination address.
*
* @see udp_disconnect() udp_send()
*/
err_t
udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
struct ip_addr *dst_ip, u16_t dst_port)
{
err_t err;
/* temporary space for current PCB remote address */
struct ip_addr pcb_remote_ip;
u16_t pcb_remote_port;
/* remember current remote peer address of PCB */
pcb_remote_ip.addr = pcb->remote_ip.addr;
pcb_remote_port = pcb->remote_port;
/* copy packet destination address to PCB remote peer address */
pcb->remote_ip.addr = dst_ip->addr;
pcb->remote_port = dst_port;
/* send to the packet destination address */
err = udp_send(pcb, p);
/* restore PCB remote peer address */
pcb->remote_ip.addr = pcb_remote_ip.addr;
pcb->remote_port = pcb_remote_port;
return err;
}
/**
* Send data using UDP.
*
* @param pcb UDP PCB used to send the data.
* @param pbuf chain of pbuf's to be sent.
*
* @return lwIP error code.
* - ERR_OK. Successful. No error occured.
* - ERR_MEM. Out of memory.
* - ERR_RTE. Could not find route to destination address.
*
* @see udp_disconnect() udp_sendto()
*/
err_t
udp_send(struct udp_pcb *pcb, struct pbuf *p)
{
struct udp_hdr *udphdr;
struct netif *netif;
struct ip_addr *src_ip;
err_t err;
struct pbuf *q; /* q will be sent down the stack */
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, ("udp_send\n"));
/* if the PCB is not yet bound to a port, bind it here */
if (pcb->local_port == 0) {
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 2, ("udp_send: not yet bound to a port, binding now\n"));
err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
if (err != ERR_OK) {
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 2, ("udp_send: forced port bind failed\n"));
return err;
}
}
/* find the outgoing network interface for this packet */
netif = ip_route(&(pcb->remote_ip));
/* no outgoing network interface could be found? */
if (netif == NULL) {
LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_send: No route to 0x%"X32_F"\n", pcb->remote_ip.addr));
UDP_STATS_INC(udp.rterr);
return ERR_RTE;
}
/* not enough space to add an UDP header to first pbuf in given p chain? */
if (pbuf_header(p, UDP_HLEN)) {
/* allocate header in a seperate new pbuf */
q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM);
/* new header pbuf could not be allocated? */
if (q == NULL) {
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 2, ("udp_send: could not allocate header\n"));
return ERR_MEM;
}
/* chain header q in front of given pbuf p */
pbuf_chain(q, p);
/* { first pbuf q points to header pbuf } */
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
/* adding a header within p succeeded */
} else {
/* first pbuf q equals given pbuf */
q = p;
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p));
}
/* { q now represents the packet to be sent } */
udphdr = q->payload;
udphdr->src = htons(pcb->local_port);
udphdr->dest = htons(pcb->remote_port);
/* in UDP, 0 checksum means 'no checksum' */
udphdr->chksum = 0x0000;
/* PCB local address is IP_ANY_ADDR? */
if (ip_addr_isany(&pcb->local_ip)) {
/* use outgoing network interface IP address as source address */
src_ip = &(netif->ip_addr);
} else {
/* use UDP PCB local IP address as source address */
src_ip = &(pcb->local_ip);
}
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len));
/* UDP Lite protocol? */
if (pcb->flags & UDP_FLAGS_UDPLITE) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len));
/* set UDP message length in UDP header */
udphdr->len = htons(pcb->chksum_len);
/* calculate checksum */
#if CHECKSUM_GEN_UDP
udphdr->chksum = inet_chksum_pseudo(q, src_ip, &(pcb->remote_ip),
IP_PROTO_UDP, pcb->chksum_len);
/* chksum zero must become 0xffff, as zero means 'no checksum' */
if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
#else
udphdr->chksum = 0x0000;
#endif
/* output to IP */
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDPLITE,)\n"));
err = ip_output_if (q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
/* UDP */
} else {
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len));
udphdr->len = htons(q->tot_len);
/* calculate checksum */
#if CHECKSUM_GEN_UDP
if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
udphdr->chksum = inet_chksum_pseudo(q, src_ip, &pcb->remote_ip, IP_PROTO_UDP, q->tot_len);
/* chksum zero must become 0xffff, as zero means 'no checksum' */
if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
}
#else
udphdr->chksum = 0x0000;
#endif
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum));
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
/* output to IP */
err = ip_output_if(q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
}
/* TODO: must this be increased even if error occured? */
snmp_inc_udpoutdatagrams();
/* did we chain a seperate header pbuf earlier? */
if (q != p) {
/* free the header pbuf */
pbuf_free(q); q = NULL;
/* { p is still referenced by the caller, and will live on } */
}
UDP_STATS_INC(udp.xmit);
return err;
}
/**
* Bind an UDP PCB.
*
* @param pcb UDP PCB to be bound with a local address ipaddr and port.
* @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to
* bind to all local interfaces.
* @param port local UDP port to bind with.
*
* @return lwIP error code.
* - ERR_OK. Successful. No error occured.
* - ERR_USE. The specified ipaddr and port are already bound to by
* another UDP PCB.
*
* @see udp_disconnect()
*/
err_t
udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
{
struct udp_pcb *ipcb;
u8_t rebind;
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, ("udp_bind(ipaddr = "));
ip_addr_debug_print(UDP_DEBUG, ipaddr);
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, (", port = %"U16_F")\n", port));
rebind = 0;
/* Check for double bind and rebind of the same pcb */
for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
/* is this UDP PCB already on active list? */
if (pcb == ipcb) {
/* pcb may occur at most once in active list */
LWIP_ASSERT("rebind == 0", rebind == 0);
/* pcb already in list, just rebind */
rebind = 1;
}
/* this code does not allow upper layer to share a UDP port for
listening to broadcast or multicast traffic (See SO_REUSE_ADDR and
SO_REUSE_PORT under *BSD). TODO: See where it fits instead, OR
combine with implementation of UDP PCB flags. Leon Woestenberg. */
#ifdef LWIP_UDP_TODO
/* port matches that of PCB in list? */
else if ((ipcb->local_port == port) &&
/* IP address matches, or one is IP_ADDR_ANY? */
(ip_addr_isany(&(ipcb->local_ip)) ||
ip_addr_isany(ipaddr) ||
ip_addr_cmp(&(ipcb->local_ip), ipaddr))) {
/* other PCB already binds to this local IP and port */
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: local port %"U16_F" already bound by another pcb\n", port));
return ERR_USE;
}
#endif
}
ip_addr_set(&pcb->local_ip, ipaddr);
/* no port specified? */
if (port == 0) {
#ifndef UDP_LOCAL_PORT_RANGE_START
#define UDP_LOCAL_PORT_RANGE_START 4096
#define UDP_LOCAL_PORT_RANGE_END 0x7fff
#endif
port = UDP_LOCAL_PORT_RANGE_START;
ipcb = udp_pcbs;
while ((ipcb != NULL) && (port != UDP_LOCAL_PORT_RANGE_END)) {
if (ipcb->local_port == port) {
port++;
ipcb = udp_pcbs;
} else
ipcb = ipcb->next;
}
if (ipcb != NULL) {
/* no more ports available in local range */
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n"));
return ERR_USE;
}
}
pcb->local_port = port;
/* pcb not active yet? */
if (rebind == 0) {
/* place the PCB on the active list if not already there */
pcb->next = udp_pcbs;
udp_pcbs = pcb;
}
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_bind: bound to %"U16_F".%"U16_F".%"U16_F".%"U16_F", port %"U16_F"\n",
(u16_t)(ntohl(pcb->local_ip.addr) >> 24 & 0xff),
(u16_t)(ntohl(pcb->local_ip.addr) >> 16 & 0xff),
(u16_t)(ntohl(pcb->local_ip.addr) >> 8 & 0xff),
(u16_t)(ntohl(pcb->local_ip.addr) & 0xff), pcb->local_port));
return ERR_OK;
}
/**
* Connect an UDP PCB.
*
* This will associate the UDP PCB with the remote address.
*
* @param pcb UDP PCB to be connected with remote address ipaddr and port.
* @param ipaddr remote IP address to connect with.
* @param port remote UDP port to connect with.
*
* @return lwIP error code
*
* @see udp_disconnect()
*/
err_t
udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
{
struct udp_pcb *ipcb;
if (pcb->local_port == 0) {
err_t err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
if (err != ERR_OK)
return err;
}
ip_addr_set(&pcb->remote_ip, ipaddr);
pcb->remote_port = port;
pcb->flags |= UDP_FLAGS_CONNECTED;
/** TODO: this functionality belongs in upper layers */
#ifdef LWIP_UDP_TODO
/* Nail down local IP for netconn_addr()/getsockname() */
if (ip_addr_isany(&pcb->local_ip) && !ip_addr_isany(&pcb->remote_ip)) {
struct netif *netif;
if ((netif = ip_route(&(pcb->remote_ip))) == NULL) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", pcb->remote_ip.addr));
UDP_STATS_INC(udp.rterr);
return ERR_RTE;
}
/** TODO: this will bind the udp pcb locally, to the interface which
is used to route output packets to the remote address. However, we
might want to accept incoming packets on any interface! */
pcb->local_ip = netif->ip_addr;
} else if (ip_addr_isany(&pcb->remote_ip)) {
pcb->local_ip.addr = 0;
}
#endif
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_connect: connected to %"U16_F".%"U16_F".%"U16_F".%"U16_F",port %"U16_F"\n",
(u16_t)(ntohl(pcb->remote_ip.addr) >> 24 & 0xff),
(u16_t)(ntohl(pcb->remote_ip.addr) >> 16 & 0xff),
(u16_t)(ntohl(pcb->remote_ip.addr) >> 8 & 0xff),
(u16_t)(ntohl(pcb->remote_ip.addr) & 0xff), pcb->remote_port));
/* Insert UDP PCB into the list of active UDP PCBs. */
for(ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
if (pcb == ipcb) {
/* already on the list, just return */
return ERR_OK;
}
}
/* PCB not yet on the list, add PCB now */
pcb->next = udp_pcbs;
udp_pcbs = pcb;
return ERR_OK;
}
void
udp_disconnect(struct udp_pcb *pcb)
{
/* reset remote address association */
ip_addr_set(&pcb->remote_ip, IP_ADDR_ANY);
pcb->remote_port = 0;
/* mark PCB as unconnected */
pcb->flags &= ~UDP_FLAGS_CONNECTED;
}
void
udp_recv(struct udp_pcb *pcb,
void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p,
struct ip_addr *addr, u16_t port),
void *recv_arg)
{
/* remember recv() callback and user data */
pcb->recv = recv;
pcb->recv_arg = recv_arg;
}
/**
* Remove an UDP PCB.
*
* @param pcb UDP PCB to be removed. The PCB is removed from the list of
* UDP PCB's and the data structure is freed from memory.
*
* @see udp_new()
*/
void
udp_remove(struct udp_pcb *pcb)
{
struct udp_pcb *pcb2;
/* pcb to be removed is first in list? */
if (udp_pcbs == pcb) {
/* make list start at 2nd pcb */
udp_pcbs = udp_pcbs->next;
/* pcb not 1st in list */
} else for(pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
/* find pcb in udp_pcbs list */
if (pcb2->next != NULL && pcb2->next == pcb) {
/* remove pcb from list */
pcb2->next = pcb->next;
}
}
memp_free(MEMP_UDP_PCB, pcb);
}
/**
* Create a UDP PCB.
*
* @return The UDP PCB which was created. NULL if the PCB data structure
* could not be allocated.
*
* @see udp_remove()
*/
struct udp_pcb *
udp_new(void) {
struct udp_pcb *pcb;
pcb = memp_malloc(MEMP_UDP_PCB);
/* could allocate UDP PCB? */
if (pcb != NULL) {
/* initialize PCB to all zeroes */
memset(pcb, 0, sizeof(struct udp_pcb));
pcb->ttl = UDP_TTL;
}
return pcb;
}
#if UDP_DEBUG
void
udp_debug_print(struct udp_hdr *udphdr)
{
LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n"));
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n",
ntohs(udphdr->src), ntohs(udphdr->dest)));
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | 0x%04"X16_F" | (len, chksum)\n",
ntohs(udphdr->len), ntohs(udphdr->chksum)));
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
}
#endif /* UDP_DEBUG */
#endif /* LWIP_UDP */

View File

@@ -0,0 +1,112 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __LWIP_ICMP_H__
#define __LWIP_ICMP_H__
#include "lwip/arch.h"
#include "lwip/opt.h"
#include "lwip/pbuf.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#define ICMP_ER 0 /* echo reply */
#define ICMP_DUR 3 /* destination unreachable */
#define ICMP_SQ 4 /* source quench */
#define ICMP_RD 5 /* redirect */
#define ICMP_ECHO 8 /* echo */
#define ICMP_TE 11 /* time exceeded */
#define ICMP_PP 12 /* parameter problem */
#define ICMP_TS 13 /* timestamp */
#define ICMP_TSR 14 /* timestamp reply */
#define ICMP_IRQ 15 /* information request */
#define ICMP_IR 16 /* information reply */
enum icmp_dur_type {
ICMP_DUR_NET = 0, /* net unreachable */
ICMP_DUR_HOST = 1, /* host unreachable */
ICMP_DUR_PROTO = 2, /* protocol unreachable */
ICMP_DUR_PORT = 3, /* port unreachable */
ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */
ICMP_DUR_SR = 5 /* source route failed */
};
enum icmp_te_type {
ICMP_TE_TTL = 0, /* time to live exceeded in transit */
ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */
};
void icmp_input(struct pbuf *p, struct netif *inp);
void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t);
void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t);
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct icmp_echo_hdr {
PACK_STRUCT_FIELD(u16_t _type_code);
PACK_STRUCT_FIELD(u16_t chksum);
PACK_STRUCT_FIELD(u16_t id);
PACK_STRUCT_FIELD(u16_t seqno);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
PACK_STRUCT_BEGIN
struct icmp_dur_hdr {
PACK_STRUCT_FIELD(u16_t _type_code);
PACK_STRUCT_FIELD(u16_t chksum);
PACK_STRUCT_FIELD(u32_t unused);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
PACK_STRUCT_BEGIN
struct icmp_te_hdr {
PACK_STRUCT_FIELD(u16_t _type_code);
PACK_STRUCT_FIELD(u16_t chksum);
PACK_STRUCT_FIELD(u32_t unused);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
#define ICMPH_TYPE(hdr) (ntohs((hdr)->_type_code) >> 8)
#define ICMPH_CODE(hdr) (ntohs((hdr)->_type_code) & 0xff)
#define ICMPH_TYPE_SET(hdr, type) ((hdr)->_type_code = htons(ICMPH_CODE(hdr) | ((type) << 8)))
#define ICMPH_CODE_SET(hdr, code) ((hdr)->_type_code = htons((code) | (ICMPH_TYPE(hdr) << 8)))
#endif /* __LWIP_ICMP_H__ */

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __LWIP_INET_H__
#define __LWIP_INET_H__
#include "lwip/arch.h"
#include "lwip/opt.h"
#include "lwip/pbuf.h"
#include "lwip/ip_addr.h"
u16_t inet_chksum(void *dataptr, u16_t len);
#if 0 /* optimized routine */
u16_t inet_chksum4(u8_t *dataptr, u16_t len);
#endif
u16_t inet_chksum_pbuf(struct pbuf *p);
u16_t inet_chksum_pseudo(struct pbuf *p,
struct ip_addr *src, struct ip_addr *dest,
u8_t proto, u16_t proto_len);
u32_t inet_addr(const char *cp);
s8_t inet_aton(const char *cp, struct in_addr *addr);
char *inet_ntoa(struct in_addr addr); /* returns ptr to static buffer; not reentrant! */
#ifdef htons
#undef htons
#endif /* htons */
#ifdef htonl
#undef htonl
#endif /* htonl */
#ifdef ntohs
#undef ntohs
#endif /* ntohs */
#ifdef ntohl
#undef ntohl
#endif /* ntohl */
#if BYTE_ORDER == BIG_ENDIAN
#define htons(x) (x)
#define ntohs(x) (x)
#define htonl(x) (x)
#define ntohl(x) (x)
#else
#ifdef LWIP_PREFIX_BYTEORDER_FUNCS
/* workaround for naming collisions on some platforms */
#define htons lwip_htons
#define ntohs lwip_ntohs
#define htonl lwip_htonl
#define ntohl lwip_ntohl
#endif
u16_t htons(u16_t x);
u16_t ntohs(u16_t x);
u32_t htonl(u32_t x);
u32_t ntohl(u32_t x);
#endif
#endif /* __LWIP_INET_H__ */

View File

@@ -0,0 +1,154 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __LWIP_IP_H__
#define __LWIP_IP_H__
#include "lwip/arch.h"
#include "lwip/def.h"
#include "lwip/pbuf.h"
#include "lwip/ip_addr.h"
#include "lwip/err.h"
void ip_init(void);
struct netif *ip_route(struct ip_addr *dest);
err_t ip_input(struct pbuf *p, struct netif *inp);
err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t tos, u8_t proto);
err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t tos, u8_t proto,
struct netif *netif);
#define IP_HLEN 20
#define IP_PROTO_ICMP 1
#define IP_PROTO_UDP 17
#define IP_PROTO_UDPLITE 170
#define IP_PROTO_TCP 6
/* This is passed as the destination address to ip_output_if (not
to ip_output), meaning that an IP header already is constructed
in the pbuf. This is used when TCP retransmits. */
#ifdef IP_HDRINCL
#undef IP_HDRINCL
#endif /* IP_HDRINCL */
#define IP_HDRINCL NULL
/* This is the common part of all PCB types. It needs to be at the
beginning of a PCB type definition. It is located here so that
changes to this common part are made in one location instead of
having to change all PCB structs. */
#define IP_PCB struct ip_addr local_ip; \
struct ip_addr remote_ip; \
/* Socket options */ \
u16_t so_options; \
/* Type Of Service */ \
u8_t tos; \
/* Time To Live */ \
u8_t ttl
/*
* Option flags per-socket. These are the same like SO_XXX.
*/
#define SOF_DEBUG (u16_t)0x0001U /* turn on debugging info recording */
#define SOF_ACCEPTCONN (u16_t)0x0002U /* socket has had listen() */
#define SOF_REUSEADDR (u16_t)0x0004U /* allow local address reuse */
#define SOF_KEEPALIVE (u16_t)0x0008U /* keep connections alive */
#define SOF_DONTROUTE (u16_t)0x0010U /* just use interface addresses */
#define SOF_BROADCAST (u16_t)0x0020U /* permit sending of broadcast msgs */
#define SOF_USELOOPBACK (u16_t)0x0040U /* bypass hardware when possible */
#define SOF_LINGER (u16_t)0x0080U /* linger on close if data present */
#define SOF_OOBINLINE (u16_t)0x0100U /* leave received OOB data in line */
#define SOF_REUSEPORT (u16_t)0x0200U /* allow local address & port reuse */
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct ip_hdr {
/* version / header length / type of service */
PACK_STRUCT_FIELD(u16_t _v_hl_tos);
/* total length */
PACK_STRUCT_FIELD(u16_t _len);
/* identification */
PACK_STRUCT_FIELD(u16_t _id);
/* fragment offset field */
PACK_STRUCT_FIELD(u16_t _offset);
#define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
/* time to live / protocol*/
PACK_STRUCT_FIELD(u16_t _ttl_proto);
/* checksum */
PACK_STRUCT_FIELD(u16_t _chksum);
/* source and destination IP addresses */
PACK_STRUCT_FIELD(struct ip_addr src);
PACK_STRUCT_FIELD(struct ip_addr dest);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
#define IPH_V(hdr) (ntohs((hdr)->_v_hl_tos) >> 12)
#define IPH_HL(hdr) ((ntohs((hdr)->_v_hl_tos) >> 8) & 0x0f)
#define IPH_TOS(hdr) (ntohs((hdr)->_v_hl_tos) & 0xff)
#define IPH_LEN(hdr) ((hdr)->_len)
#define IPH_ID(hdr) ((hdr)->_id)
#define IPH_OFFSET(hdr) ((hdr)->_offset)
#define IPH_TTL(hdr) (ntohs((hdr)->_ttl_proto) >> 8)
#define IPH_PROTO(hdr) (ntohs((hdr)->_ttl_proto) & 0xff)
#define IPH_CHKSUM(hdr) ((hdr)->_chksum)
#define IPH_VHLTOS_SET(hdr, v, hl, tos) (hdr)->_v_hl_tos = (htons(((v) << 12) | ((hl) << 8) | (tos)))
#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len)
#define IPH_ID_SET(hdr, id) (hdr)->_id = (id)
#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off)
#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl_proto = (htons(IPH_PROTO(hdr) | ((ttl) << 8)))
#define IPH_PROTO_SET(hdr, proto) (hdr)->_ttl_proto = (htons((proto) | (IPH_TTL(hdr) << 8)))
#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum)
#if IP_DEBUG
void ip_debug_print(struct pbuf *p);
#else
#define ip_debug_print(p)
#endif /* IP_DEBUG */
#endif /* __LWIP_IP_H__ */

View File

@@ -0,0 +1,159 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __LWIP_IP_ADDR_H__
#define __LWIP_IP_ADDR_H__
#include "lwip/arch.h"
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct ip_addr {
PACK_STRUCT_FIELD(u32_t addr);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct ip_addr2 {
PACK_STRUCT_FIELD(u16_t addrw[2]);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
/* For compatibility with BSD code */
struct in_addr {
u32_t s_addr;
};
struct netif;
extern const struct ip_addr ip_addr_any;
extern const struct ip_addr ip_addr_broadcast;
/** IP_ADDR_ can be used as a fixed IP address
* for the wildcard and the broadcast address
*/
#define IP_ADDR_ANY ((struct ip_addr *)&ip_addr_any)
#define IP_ADDR_BROADCAST ((struct ip_addr *)&ip_addr_broadcast)
#define INADDR_NONE ((u32_t) 0xffffffff) /* 255.255.255.255 */
#define INADDR_LOOPBACK ((u32_t) 0x7f000001) /* 127.0.0.1 */
/* Definitions of the bits in an Internet address integer.
On subnets, host and network parts are found according to
the subnet mask, not these masks. */
#define IN_CLASSA(a) ((((u32_t)(a)) & 0x80000000) == 0)
#define IN_CLASSA_NET 0xff000000
#define IN_CLASSA_NSHIFT 24
#define IN_CLASSA_HOST (0xffffffff & ~IN_CLASSA_NET)
#define IN_CLASSA_MAX 128
#define IN_CLASSB(a) ((((u32_t)(a)) & 0xc0000000) == 0x80000000)
#define IN_CLASSB_NET 0xffff0000
#define IN_CLASSB_NSHIFT 16
#define IN_CLASSB_HOST (0xffffffff & ~IN_CLASSB_NET)
#define IN_CLASSB_MAX 65536
#define IN_CLASSC(a) ((((u32_t)(a)) & 0xe0000000) == 0xc0000000)
#define IN_CLASSC_NET 0xffffff00
#define IN_CLASSC_NSHIFT 8
#define IN_CLASSC_HOST (0xffffffff & ~IN_CLASSC_NET)
#define IN_CLASSD(a) (((u32_t)(a) & 0xf0000000) == 0xe0000000)
#define IN_CLASSD_NET 0xf0000000 /* These ones aren't really */
#define IN_CLASSD_NSHIFT 28 /* net and host fields, but */
#define IN_CLASSD_HOST 0x0fffffff /* routing needn't know. */
#define IN_MULTICAST(a) IN_CLASSD(a)
#define IN_EXPERIMENTAL(a) (((u32_t)(a) & 0xf0000000) == 0xf0000000)
#define IN_BADCLASS(a) (((u32_t)(a) & 0xf0000000) == 0xf0000000)
#define IN_LOOPBACKNET 127 /* official! */
#define IP4_ADDR(ipaddr, a,b,c,d) (ipaddr)->addr = htonl(((u32_t)(a & 0xff) << 24) | ((u32_t)(b & 0xff) << 16) | \
((u32_t)(c & 0xff) << 8) | (u32_t)(d & 0xff))
#define ip_addr_set(dest, src) (dest)->addr = \
((src) == NULL? 0:\
(src)->addr)
/**
* Determine if two address are on the same network.
*
* @arg addr1 IP address 1
* @arg addr2 IP address 2
* @arg mask network identifier mask
* @return !0 if the network identifiers of both address match
*/
#define ip_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \
(mask)->addr) == \
((addr2)->addr & \
(mask)->addr))
#define ip_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr)
#define ip_addr_isany(addr1) ((addr1) == NULL || (addr1)->addr == 0)
u8_t ip_addr_isbroadcast(struct ip_addr *, struct netif *);
#define ip_addr_ismulticast(addr1) (((addr1)->addr & ntohl(0xf0000000)) == ntohl(0xe0000000))
#define ip_addr_debug_print(debug, ipaddr) LWIP_DEBUGF(debug, ("%"U16_F".%"U16_F".%"U16_F".%"U16_F, \
ipaddr?(u16_t)(ntohl((ipaddr)->addr) >> 24) & 0xff:0, \
ipaddr?(u16_t)(ntohl((ipaddr)->addr) >> 16) & 0xff:0, \
ipaddr?(u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff:0, \
ipaddr?(u16_t)ntohl((ipaddr)->addr) & 0xff:0U))
/* cast to unsigned int, as it is used as argument to printf functions
* which expect integer arguments. CSi: use cc.h formatters (conversion chars)! */
#define ip4_addr1(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 24) & 0xff)
#define ip4_addr2(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 16) & 0xff)
#define ip4_addr3(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff)
#define ip4_addr4(ipaddr) ((u16_t)(ntohl((ipaddr)->addr)) & 0xff)
#endif /* __LWIP_IP_ADDR_H__ */

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Jani Monoses <jani@iv.ro>
*
*/
#ifndef __LWIP_IP_FRAG_H__
#define __LWIP_IP_FRAG_H__
#include "lwip/err.h"
#include "lwip/pbuf.h"
#include "lwip/netif.h"
#include "lwip/ip_addr.h"
void ip_reass_tmr(void);
struct pbuf * ip_reass(struct pbuf *p);
err_t ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest);
#endif /* __LWIP_IP_FRAG_H__ */

View File

@@ -0,0 +1,90 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __LWIP_ICMP_H__
#define __LWIP_ICMP_H__
#include "lwip/arch.h"
#include "lwip/opt.h"
#include "lwip/pbuf.h"
#include "lwip/netif.h"
#define ICMP6_DUR 1
#define ICMP6_TE 3
#define ICMP6_ECHO 128 /* echo */
#define ICMP6_ER 129 /* echo reply */
enum icmp_dur_type {
ICMP_DUR_NET = 0, /* net unreachable */
ICMP_DUR_HOST = 1, /* host unreachable */
ICMP_DUR_PROTO = 2, /* protocol unreachable */
ICMP_DUR_PORT = 3, /* port unreachable */
ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */
ICMP_DUR_SR = 5 /* source route failed */
};
enum icmp_te_type {
ICMP_TE_TTL = 0, /* time to live exceeded in transit */
ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */
};
void icmp_input(struct pbuf *p, struct netif *inp);
void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t);
void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t);
struct icmp_echo_hdr {
u8_t type;
u8_t icode;
u16_t chksum;
u16_t id;
u16_t seqno;
};
struct icmp_dur_hdr {
u8_t type;
u8_t icode;
u16_t chksum;
u32_t unused;
};
struct icmp_te_hdr {
u8_t type;
u8_t icode;
u16_t chksum;
u32_t unused;
};
#endif /* __LWIP_ICMP_H__ */

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __LWIP_INET_H__
#define __LWIP_INET_H__
#include "lwip/arch.h"
#include "lwip/opt.h"
#include "lwip/pbuf.h"
#include "lwip/ip_addr.h"
u16_t inet_chksum(void *data, u16_t len);
u16_t inet_chksum_pbuf(struct pbuf *p);
u16_t inet_chksum_pseudo(struct pbuf *p,
struct ip_addr *src, struct ip_addr *dest,
u8_t proto, u32_t proto_len);
u32_t inet_addr(const char *cp);
s8_t inet_aton(const char *cp, struct in_addr *addr);
#ifndef _MACHINE_ENDIAN_H_
#ifndef _NETINET_IN_H
#ifndef _LINUX_BYTEORDER_GENERIC_H
u16_t htons(u16_t n);
u16_t ntohs(u16_t n);
u32_t htonl(u32_t n);
u32_t ntohl(u32_t n);
#endif /* _LINUX_BYTEORDER_GENERIC_H */
#endif /* _NETINET_IN_H */
#endif /* _MACHINE_ENDIAN_H_ */
#endif /* __LWIP_INET_H__ */

Some files were not shown because too many files have changed in this diff Show More