]> rtime.felk.cvut.cz Git - lincan.git/commitdiff
Merge branch 'master' into can-usb1
authorppisa <pisa@cmp.felk.cvut.cz>
Sun, 2 Nov 2008 11:59:16 +0000 (12:59 +0100)
committerppisa <pisa@cmp.felk.cvut.cz>
Sun, 2 Nov 2008 11:59:16 +0000 (12:59 +0100)
205 files changed:
build-embedded.sh [new file with mode: 0755]
embedded/Makefile [new file with mode: 0644]
embedded/Makefile.omk [new file with mode: 0644]
embedded/README.txt [new file with mode: 0644]
embedded/app/Makefile [new file with mode: 0644]
embedded/app/Makefile.omk [new file with mode: 0644]
embedded/app/usbcan/Makefile [new file with mode: 0644]
embedded/app/usbcan/Makefile.omk [new file with mode: 0644]
embedded/app/usbcan/can.c [new file with mode: 0644]
embedded/app/usbcan/can/can.h [new file with mode: 0644]
embedded/app/usbcan/can/can_queue.h [new file with mode: 0644]
embedded/app/usbcan/can/can_sysdep.h [new file with mode: 0644]
embedded/app/usbcan/can/can_sysless.h [new file with mode: 0644]
embedded/app/usbcan/can/canmsg.h [new file with mode: 0644]
embedded/app/usbcan/can/constants.h [new file with mode: 0644]
embedded/app/usbcan/can/devcommon.h [new file with mode: 0644]
embedded/app/usbcan/can/errno-base.h [new file with mode: 0755]
embedded/app/usbcan/can/errno.h [new file with mode: 0755]
embedded/app/usbcan/can/finish.h [new file with mode: 0644]
embedded/app/usbcan/can/i82527.h [new file with mode: 0644]
embedded/app/usbcan/can/main.h [new file with mode: 0644]
embedded/app/usbcan/can/modparms.h [new file with mode: 0644]
embedded/app/usbcan/can/setup.h [new file with mode: 0644]
embedded/app/usbcan/can/sja1000p.h [new file with mode: 0644]
embedded/app/usbcan/can/ul_listbase.h [new file with mode: 0644]
embedded/app/usbcan/can/ul_usb1.h [new file with mode: 0644]
embedded/app/usbcan/can_quesysless.c [new file with mode: 0644]
embedded/app/usbcan/can_queue.c [new file with mode: 0644]
embedded/app/usbcan/devcommon.c [new file with mode: 0644]
embedded/app/usbcan/finish.c [new file with mode: 0644]
embedded/app/usbcan/main.c [new file with mode: 0644]
embedded/app/usbcan/setup.c [new file with mode: 0644]
embedded/app/usbcan/sja1000p.c [new file with mode: 0644]
embedded/app/usbcan/ul_usb1.c [new file with mode: 0644]
embedded/app/usbcan/usb/usb_defs.h [new file with mode: 0644]
embedded/app/usbcan/usb/usb_vend.h [new file with mode: 0644]
embedded/app/usbcan/usb_srq.c [new file with mode: 0644]
embedded/app/usbcan/usb_vend.c [new file with mode: 0644]
embedded/arch/Makefile [new file with mode: 0644]
embedded/arch/Makefile.omk [new file with mode: 0644]
embedded/arch/arm/Makefile [new file with mode: 0644]
embedded/arch/arm/Makefile.omk [new file with mode: 0644]
embedded/arch/arm/generic/Makefile [new file with mode: 0644]
embedded/arch/arm/generic/Makefile.omk [new file with mode: 0644]
embedded/arch/arm/generic/defines/Makefile [new file with mode: 0644]
embedded/arch/arm/generic/defines/Makefile.omk [new file with mode: 0644]
embedded/arch/arm/generic/defines/cpu_def.h [new file with mode: 0644]
embedded/arch/arm/generic/defines/hal_intr.h [new file with mode: 0644]
embedded/arch/arm/generic/defines/types.h [new file with mode: 0644]
embedded/arch/arm/generic/libs/Makefile [new file with mode: 0644]
embedded/arch/arm/generic/libs/Makefile.omk [new file with mode: 0644]
embedded/arch/arm/generic/libs/misc/Makefile [new file with mode: 0644]
embedded/arch/arm/generic/libs/misc/Makefile.omk [new file with mode: 0644]
embedded/arch/arm/generic/libs/misc/system_stub.c [new file with mode: 0644]
embedded/arch/arm/generic/libs/misc/system_stub.h [new file with mode: 0644]
embedded/arch/arm/generic/libs/misc/undef_support.c [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/Makefile [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/Makefile.omk [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/defines/LPC210x.h [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/defines/LPC214x.h [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/defines/LPC21xx.h [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/defines/LPC22xx.h [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/defines/Makefile [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/defines/Makefile.omk [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/defines/armVIC.h [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/defines/lpcADC-214x.h [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/defines/lpcADC.h [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/defines/lpcEMC.h [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/defines/lpcGPIO.h [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/defines/lpcI2C.h [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/defines/lpcPIN.h [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/defines/lpcRTC.h [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/defines/lpcSCB.h [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/defines/lpcSPI.h [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/defines/lpcTMR.h [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/defines/lpcUART.h [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/defines/lpcUSB.h [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/defines/lpcVIC.h [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/defines/lpcWD.h [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/libs/Makefile [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/libs/Makefile.omk [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/libs/hal/Makefile [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/libs/hal/Makefile.omk [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/libs/hal/hal.c [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/libs/hal/hal_ints.h [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/libs/hal/hal_machperiph.c [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/libs/hal/hal_machperiph.h [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/libs/hal/ivt.S [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/libs/hal/startup.S [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/libs/iap/Makefile [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/libs/iap/Makefile.omk [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/libs/iap/iap.c [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/libs/iap/iap_asm.S [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/libs/iap/iap_kvpb.c [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/libs/iap/lpciap.h [new file with mode: 0644]
embedded/arch/arm/mach-lpc21xx/libs/iap/lpciap_kvpb.h [new file with mode: 0644]
embedded/arch/generic/Makefile [new file with mode: 0644]
embedded/arch/generic/Makefile.omk [new file with mode: 0644]
embedded/arch/generic/defines/Makefile [new file with mode: 0644]
embedded/arch/generic/defines/Makefile.omk [new file with mode: 0644]
embedded/arch/generic/defines/byteswap.h [new file with mode: 0644]
embedded/arch/generic/defines/endian.h [new file with mode: 0644]
embedded/arch/generic/defines/lt_timer.h [new file with mode: 0644]
embedded/arch/generic/defines/lt_timer_types.h [new file with mode: 0644]
embedded/board/Makefile [new file with mode: 0644]
embedded/board/Makefile.omk [new file with mode: 0644]
embedded/board/arm/Makefile [new file with mode: 0644]
embedded/board/arm/Makefile.omk [new file with mode: 0644]
embedded/board/arm/ul_usb1/Makefile [new file with mode: 0644]
embedded/board/arm/ul_usb1/Makefile.omk [new file with mode: 0644]
embedded/board/arm/ul_usb1/config/config.bell-keypad [new file with mode: 0644]
embedded/board/arm/ul_usb1/config/config.garage-gate [new file with mode: 0644]
embedded/board/arm/ul_usb1/config/config.ha-switch [new file with mode: 0644]
embedded/board/arm/ul_usb1/config/config.ha-switch-ulboot [new file with mode: 0644]
embedded/board/arm/ul_usb1/config/config.u2uv2 [new file with mode: 0644]
embedded/board/arm/ul_usb1/config/config.ul_usb1 [new file with mode: 0644]
embedded/board/arm/ul_usb1/config/config.ulboot [new file with mode: 0644]
embedded/board/arm/ul_usb1/config/config.usbcan [new file with mode: 0644]
embedded/board/arm/ul_usb1/defines/Makefile [new file with mode: 0644]
embedded/board/arm/ul_usb1/defines/Makefile.omk [new file with mode: 0644]
embedded/board/arm/ul_usb1/defines/system_def-ha-switch.h [new file with mode: 0644]
embedded/board/arm/ul_usb1/defines/system_def-hisc-garage-gate.h [new file with mode: 0644]
embedded/board/arm/ul_usb1/defines/system_def-hisc-keypad.h [new file with mode: 0644]
embedded/board/arm/ul_usb1/defines/system_def.h [new file with mode: 0644]
embedded/board/arm/ul_usb1/libs/Makefile [new file with mode: 0644]
embedded/board/arm/ul_usb1/libs/Makefile.omk [new file with mode: 0644]
embedded/board/arm/ul_usb1/libs/bspbase/Makefile [new file with mode: 0644]
embedded/board/arm/ul_usb1/libs/bspbase/Makefile.omk [new file with mode: 0644]
embedded/board/arm/ul_usb1/libs/bspbase/bsp0hwinit.c [new file with mode: 0644]
embedded/board/arm/ul_usb1/libs/bspbase/bspbase.h [new file with mode: 0644]
embedded/board/arm/ul_usb1/libs/bspbase/kbd_io_hisc.c [new file with mode: 0644]
embedded/board/arm/ul_usb1/libs/bspbase/uart.c [new file with mode: 0644]
embedded/board/arm/ul_usb1/libs/bspbase/uart.h [new file with mode: 0644]
embedded/board/arm/ul_usb1/libs/ldscripts/Makefile [new file with mode: 0644]
embedded/board/arm/ul_usb1/libs/ldscripts/Makefile.omk [new file with mode: 0644]
embedded/board/arm/ul_usb1/libs/ldscripts/keyval_loc.h [new file with mode: 0644]
embedded/board/arm/ul_usb1/libs/ldscripts/lpc2103.ld-cfg [new file with mode: 0644]
embedded/board/arm/ul_usb1/libs/ldscripts/lpc2103.ld-flash [new file with mode: 0644]
embedded/board/arm/ul_usb1/libs/ldscripts/lpc2105.ld-app [new file with mode: 0644]
embedded/board/arm/ul_usb1/libs/ldscripts/lpc2105.ld-boot [new file with mode: 0644]
embedded/board/arm/ul_usb1/libs/ldscripts/lpc2105.ld-cfg [new file with mode: 0644]
embedded/board/arm/ul_usb1/libs/ldscripts/lpc2148.ld-app [new file with mode: 0644]
embedded/board/arm/ul_usb1/libs/ldscripts/lpc2148.ld-boot [new file with mode: 0644]
embedded/board/arm/ul_usb1/libs/ldscripts/lpc2148.ld-cfg [new file with mode: 0644]
embedded/board/arm/ul_usb1/libs/ldscripts/mem_loc.h [new file with mode: 0644]
embedded/libs4c/Makefile [new file with mode: 0644]
embedded/libs4c/Makefile.omk [new file with mode: 0644]
embedded/libs4c/i2c/Makefile [new file with mode: 0644]
embedded/libs4c/i2c/Makefile.omk [new file with mode: 0644]
embedded/libs4c/i2c/i2c_c552.c [new file with mode: 0644]
embedded/libs4c/i2c/i2c_drv.c [new file with mode: 0644]
embedded/libs4c/i2c/i2c_drv.h [new file with mode: 0644]
embedded/libs4c/kbd/Makefile [new file with mode: 0644]
embedded/libs4c/kbd/Makefile.omk [new file with mode: 0644]
embedded/libs4c/kbd/kbd.h [new file with mode: 0644]
embedded/libs4c/kbd/kbd_base.c [new file with mode: 0644]
embedded/libs4c/kbd/kbd_dev_ops.c [new file with mode: 0644]
embedded/libs4c/keyval/Makefile [new file with mode: 0644]
embedded/libs4c/keyval/Makefile.omk [new file with mode: 0644]
embedded/libs4c/keyval/keyval_id.h [new file with mode: 0644]
embedded/libs4c/keyval/keyvalpb.c [new file with mode: 0644]
embedded/libs4c/keyval/keyvalpb.h [new file with mode: 0644]
embedded/libs4c/usb/Makefile [new file with mode: 0644]
embedded/libs4c/usb/Makefile.omk [new file with mode: 0644]
embedded/libs4c/usb/base/Makefile [new file with mode: 0644]
embedded/libs4c/usb/base/Makefile.omk [new file with mode: 0644]
embedded/libs4c/usb/base/usb.c [new file with mode: 0644]
embedded/libs4c/usb/base/usb/usb.h [new file with mode: 0644]
embedded/libs4c/usb/base/usb/usb_spec.h [new file with mode: 0644]
embedded/libs4c/usb/base/usb/usb_srq.h [new file with mode: 0644]
embedded/libs4c/usb/base/usb/usbdebug.h [new file with mode: 0644]
embedded/libs4c/usb/base/usbdebug.c [new file with mode: 0644]
embedded/libs4c/usb/lpcusb/Makefile [new file with mode: 0644]
embedded/libs4c/usb/lpcusb/Makefile.omk [new file with mode: 0644]
embedded/libs4c/usb/lpcusb/lpc.c [new file with mode: 0644]
embedded/libs4c/usb/lpcusb/lpcusb.c [new file with mode: 0644]
embedded/libs4c/usb/lpcusb/usb/lpc.h [new file with mode: 0644]
embedded/libs4c/usb/lpcusb/usb/lpcusb.h [new file with mode: 0644]
embedded/libs4c/usb/more/Makefile [new file with mode: 0644]
embedded/libs4c/usb/more/Makefile.omk [new file with mode: 0644]
embedded/libs4c/usb/more/usb/msc_loader.h [new file with mode: 0644]
embedded/libs4c/usb/more/usb/usb_com.h [new file with mode: 0644]
embedded/libs4c/usb/more/usb/usb_loader.h [new file with mode: 0644]
embedded/libs4c/usb/more/usb_com.c [new file with mode: 0644]
embedded/libs4c/usb/more/usb_srq.c [new file with mode: 0644]
embedded/libs4c/usb/pdiusb/Makefile [new file with mode: 0644]
embedded/libs4c/usb/pdiusb/Makefile.omk [new file with mode: 0644]
embedded/libs4c/usb/pdiusb/pdi.c [new file with mode: 0644]
embedded/libs4c/usb/pdiusb/pdiusb.c [new file with mode: 0644]
embedded/libs4c/usb/pdiusb/usb/pdi.h [new file with mode: 0644]
embedded/libs4c/usb/pdiusb/usb/pdiusb.h [new file with mode: 0644]
lincan/include/can_sysdep.h
lincan/include/main.h
lincan/include/proc.h
lincan/include/setup.h
lincan/include/usbcan.h [new file with mode: 0644]
lincan/src/Makefile.omk
lincan/src/boardlist.c
lincan/src/finish.c
lincan/src/main.c
lincan/src/modparms.c
lincan/src/proc.c
lincan/src/setup.c
lincan/src/usbcan.c [new file with mode: 0644]
omk/rules/sysless/Makefile.rules [new file with mode: 0644]

diff --git a/build-embedded.sh b/build-embedded.sh
new file mode 100755 (executable)
index 0000000..09e10cc
--- /dev/null
@@ -0,0 +1,41 @@
+SOURCE_DIRS="embedded/app embedded/arch embedded/board embedded/libs4c"
+OMK_RULES_DIR=omk/rules/sysless
+BUILD_DIR=embedded-build/can-usb1
+OMK_CONFIG=embedded/board/arm/ul_usb1/config/config.usbcan
+
+SOURCE_PATHS+=" $SOURCE_DIRS"
+SOURCE_PATHS+=" $(echo $OMK_RULES_DIR/*)"
+
+TOP_RELATIVE="$( echo "$BUILD_DIR" | sed -n -e 's#[^/]*/[^/]*#../#pg' ).."
+
+echo "SOURCE_PATHS=$SOURCE_PATHS"
+echo "TOP_RELATIVE=$TOP_RELATIVE"
+
+mkdir -p "$BUILD_DIR" || exit 1
+
+for i in $SOURCE_PATHS ; do
+  b="$(basename $i)"
+  if [ ! -e "$BUILD_DIR/$b" ] ; then
+    echo "$BUILD_DIR : ln -s $TOP_RELATIVE/$i $b"
+    ( cd "$BUILD_DIR" && ln -s "$TOP_RELATIVE/$i" "$b" ) || exit 1
+  fi
+done
+
+for i in $SOURCE_DIRS ; do
+  b="$(basename $i)"
+  if ! grep -s "\<$b\>" "$BUILD_DIR/Makefile.omk" ; then
+    echo "SUBDIRS += $b" >>"$BUILD_DIR/Makefile.omk" || exit 1
+  fi
+done
+
+if [ ! -e "$BUILD_DIR/Makefile" ] ; then
+  cp omk/Makefile "$BUILD_DIR/Makefile"
+fi
+
+if [ ! -e "$BUILD_DIR/config.omk" ] ; then
+  ( cd "$BUILD_DIR" && ln -s "$TOP_RELATIVE/$OMK_CONFIG" config.omk )
+fi
+
+( cd "$BUILD_DIR" && make default-config ) || exit 1
+
+( cd "$BUILD_DIR" && make ) || exit 1
diff --git a/embedded/Makefile b/embedded/Makefile
new file mode 100644 (file)
index 0000000..bdb6d45
--- /dev/null
@@ -0,0 +1,15 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
+# DO NOT DELETE
diff --git a/embedded/Makefile.omk b/embedded/Makefile.omk
new file mode 100644 (file)
index 0000000..c0f9113
--- /dev/null
@@ -0,0 +1,6 @@
+# -*- makefile -*-
+
+SUBDIRS = app arch board libs4c 
+
+-include $(SOURCES_DIR)/Makefile.omk-additional 
+
diff --git a/embedded/README.txt b/embedded/README.txt
new file mode 100644 (file)
index 0000000..52b1e62
--- /dev/null
@@ -0,0 +1,93 @@
+uLan embedded source tree v 0.5
+===============================
+
+This is highly experimental code, look for latest
+version on the project related pages
+
+  http://ulan.sourceforge.net/
+  http://sourceforge.net/projects/ulan
+  http://cmp.felk.cvut.cz/~pisa#ulan
+
+To build code you need to have SDCC 2.5.3-CVS.
+The snapshot past Sep 3 2005 are OK.
+The GNU make program 3.81beta3 or better is required.
+The full build has been tested on Linux based hosts only
+for now. The uLan protocol code has been successfully build
+by Keil compiler under Windows in the past.
+
+The archive has to be unpacked with symbolic links
+for now. We are thinking about rearrangement
+of the code to make it more portable and drop
+link requirements.
+
+The MCS51 is only port provided in this version.
+
+To build do
+
+  cd ul_embedded-x.y/mcs51
+  make defaul-config
+  make
+
+You should find resulting binaries in the "_compiled/bin"
+directory. The board and application is selected by used
+"config.omk" file. Example files can be found in the "configs"
+directory.
+
+The next boards and applications are supported
+
+Device: MCS51 TI MSC-1210
+   Board: ULAD-21 - AD converter and uLan2USB converter
+   Applications:
+     config.mscboot-ulad21 - uLan enabled remote boot-loader and boot-block
+     config.u2u-ulad21     - uLan to USB converter
+
+   Board: HISC - Home Information System Controller
+     config.mscboot-hisc   - boot block for distributed HISC system
+     config.blinder        - blinder controller
+     config.kswtimer       - kettle switch timer
+   
+Device: MCS51 Atmel AT89C51RD2
+     config.u2u-ps1        - AT89C51RD2 based uLan2USB converter
+
+
+The procedure to write boot-block into ULAD-21 MSC1210 based board
+requires next steps
+
+  FLASHMSC_TTY=/dev/ttyS1
+  flashmsc -d $FLASHMSC_TTY -E 0x807f
+  flashmsc -d $FLASHMSC_TTY -E 0x7fff
+  flashmsc -d $FLASHMSC_TTY -X 18432000 ulad21-hcr.hex
+  flashmsc -d $FLASHMSC_TTY -X 18432000 ulad21-boot.hex
+
+The "flashmsc" sources can be found at page
+  http://cmp.felk.cvut.cz/~pisa/#mcuutils
+
+To replace application in the converter or other uLan node
+over uLan communication protocol, next steps are required
+
+  echo Reset application if running
+  ul_sendhex -g 0 -m 0
+  echo Waiting to target to go into boot block
+  echo If application blocks, reset device at this time
+  echo to activate boot block now
+  ul_sendhex -o 0 -m 0
+  echo Found devices
+  ul_sendhex -p 64
+  echo Erasing flash
+  ul_sendhex -m 62 -t 5 -e -s 0x2000 -l 0x6000
+  sleep 2
+  echo Loading application
+  ul_sendhex -m 62 -t 5 application.hex
+
+Look for uLan driver for host side (Linux, Windows, DOS)
+uLan protocol driver. The uLan2USB converter requires
+at least version ul_drv-0.7 release.
+
+The code authors
+
+  (C) Copyright 1996-2005 by Pavel Pisa
+        http://cmp.felk.cvut.cz/~pisa
+  (C) Copyright 1996-2005 PiKRON Ltd.
+        http://www.pikron.com
+  (C) Copyright 2002-2005 Petr Smolik
+
diff --git a/embedded/app/Makefile b/embedded/app/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/app/Makefile.omk b/embedded/app/Makefile.omk
new file mode 100644 (file)
index 0000000..fd0ecae
--- /dev/null
@@ -0,0 +1,4 @@
+# -*- makefile -*-
+
+SUBDIRS = usbcan
+
diff --git a/embedded/app/usbcan/Makefile b/embedded/app/usbcan/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/app/usbcan/Makefile.omk b/embedded/app/usbcan/Makefile.omk
new file mode 100644 (file)
index 0000000..4f302d7
--- /dev/null
@@ -0,0 +1,32 @@
+# -*- makefile -*-
+
+default_CONFIG = CONFIG_APP_USBCAN=n
+
+ifeq ($(CONFIG_APP_USBCAN),y)
+
+#ULAN_ID=usbtest
+
+#default_CONFIG += CONFIG_ULOI_LT=x
+#default_CONFIG += CONFIG_ULAN_DY=x
+default_CONFIG += MACH=$(MACH)
+#default_CONFIG += ULAN_ID=$(ULAN_ID)
+default_CONFIG += CONFIG_MISC_VECT=x
+
+LOCAL_CONFIG_H = local_config.h
+
+INCLUDES += -I.
+
+#include_HEADERS  = ul_idstr.h
+
+bin_PROGRAMS = usbcan
+usbcan_SOURCES = main.c usb_srq.c can.c can_queue.c sja1000p.c can_quesysless.c devcommon.c setup.c ul_usb1.c finish.c usb_vend.c
+
+#usbtest_SOURCES +=  ul_idstr.c
+#lib_LOADLIBES =  bspbase ul_drv lpciap keyval lpciap_kvpb mach_hal uldy
+lib_LOADLIBES =  bspbase usbbase lpcusb mach_hal
+usbcan_MOREOBJS = $(USER_LIB_DIR)/system_stub.o $(USER_LIB_DIR)/ivt.o
+nobase_include_HEADERS = usb/usb_defs.h
+
+link_VARIANTS = boot
+
+endif #CONFIG_ULBOOT
diff --git a/embedded/app/usbcan/can.c b/embedded/app/usbcan/can.c
new file mode 100644 (file)
index 0000000..25d7f34
--- /dev/null
@@ -0,0 +1,136 @@
+/**
+can.c
+
+Routines for sending and receiving messages for configuration and/or
+communication over CAN network using a SJA1000 transceiver.
+For use in UL_USB1 module, it runs in Intel mode.
+See documentation for details.
+
+*/
+
+
+#include "can/can.h"
+
+/// Baud rates
+#if SJA1000_CLK==(24000000)
+       /*      Bus speed, Precaler, SJW, TSEG1, TSEG2
+        *      For SJW setting we assume 1% xtal accuracy
+        */
+       const long sja1000_freqs[3][5]=
+       {{1000, 0x00,   0xC0,   0x08,   0x10}
+       ,{250,  0x02,   0xC0,   0x0A,   0x30}
+       ,{100,  0x07,   0xC0,   0x09,   0x30}};
+       const int sja1000_freq_cnt=3;
+#endif
+
+struct can_baudparams_t canbaud;
+
+void can_comm_init()
+{
+       // Due to change in design there is CS_PIN connected with ALE_PIN and ALE_PIN connection to LPC is interrupted
+       // We don't use ALE_PIN
+       //IO0DIR|=P0_SJA1000_ALE_PIN|P0_SJA1000_CS_PIN|P0_SJA1000_RD_PIN|P0_SJA1000_WR_PIN;
+       IO0DIR|=P0_SJA1000_CS_PIN|P0_SJA1000_RD_PIN|P0_SJA1000_WR_PIN;
+       IO0DIR&=~(P0_SJA1000_INT_PIN);
+
+       SET_OUT_PIN(IO0,P0_SJA1000_CS_PIN);
+       CLR_OUT_PIN(IO1,P1_SJA1000_RST_PIN);
+       SJA1000_INIT_DELAY();
+       SET_OUT_PIN(IO0,P0_SJA1000_CS_PIN);
+       // Due to change in design there is CS_PIN connected with ALE_PIN and ALE_PIN connection to LPC is interrupted
+       //      CLR_OUT_PIN(IO0,P0_SJA1000_ALE_PIN);
+       SET_OUT_PIN(IO1,P1_SJA1000_RST_PIN);
+       SJA1000_INIT_DELAY();
+}
+
+int can_write(uint8_t address,uint8_t* data)
+{
+       IO1DIR|=0x00FF0000; // Port as output to send data
+       IO1CLR=0x00FF0000; // Clear all data on port
+       // Init
+       SET_OUT_PIN(IO0,P0_SJA1000_RD_PIN);     // Stays high on write
+       SET_OUT_PIN(IO0,P0_SJA1000_WR_PIN); // Stays high on address write
+       SET_OUT_PIN(IO0,P0_SJA1000_CS_PIN); // Sets output buffers to third state
+       SJA1000_DELAY();
+       //SET_OUT_PIN(IO0,P0_SJA1000_ALE_PIN); // Start command
+
+       // Set memory address
+       IO1SET=__val2mfld(0x00FF0000,address); // Shift data to SJA pins and output them
+       SJA1000_DELAY();
+       //CLR_OUT_PIN(IO0,P0_SJA1000_ALE_PIN); // Makes address active
+       CLR_OUT_PIN(IO0,P0_SJA1000_CS_PIN);
+       SJA1000_DELAY();
+
+       // Setting data
+       CLR_OUT_PIN(IO0,P0_SJA1000_WR_PIN);
+
+       IO1CLR=0x00FF0000;
+       IO1SET=__val2mfld(0x00FF0000,*data);
+       SJA1000_DELAY();
+       SET_OUT_PIN(IO0,P0_SJA1000_WR_PIN); // Data should be accepted by now
+       SET_OUT_PIN(IO0,P0_SJA1000_CS_PIN);
+       SJA1000_DELAY();
+       return 0;
+}
+
+int can_read(const uint8_t address,uint8_t* data)
+{
+       IO1DIR|=0x00FF0000; // Port as output to set address
+       IO1CLR=0x00FF0000; // Clear all data
+       // Init
+       SET_OUT_PIN(IO0,P0_SJA1000_WR_PIN); // Stays high on read
+       SET_OUT_PIN(IO0,P0_SJA1000_RD_PIN); // Stays high while entering address
+       SET_OUT_PIN(IO0,P0_SJA1000_CS_PIN);
+       SJA1000_DELAY();
+       //SET_OUT_PIN(IO0,P0_SJA1000_ALE_PIN);
+
+       // Request memory address
+       IO1SET=__val2mfld(0x00FF0000,address);
+       SJA1000_DELAY();
+       //CLR_OUT_PIN(IO0,P0_SJA1000_ALE_PIN);
+       CLR_OUT_PIN(IO0,P0_SJA1000_CS_PIN);
+
+       // Get data
+
+       IO1DIR&=~0x00FF0000; // Sets port as input
+       CLR_OUT_PIN(IO0,P0_SJA1000_RD_PIN);
+       SJA1000_DELAY();
+       *data=__mfld2val(0x00FF0000,IO1PIN);
+       SET_OUT_PIN(IO0,P0_SJA1000_RD_PIN);
+       SET_OUT_PIN(IO0,P0_SJA1000_CS_PIN);
+       SJA1000_DELAY();
+       return 0;
+}
+
+int can_init(){
+       uint8_t data=0,count=0;
+       do {
+               can_comm_init();
+               can_read(SJAMOD,&data);
+               if (count++ > 50)
+                       return -1;
+       } while (!(data&sjaMOD_RM));
+
+       data=sjaCDR_CLKOUT_DIV1|sjaCDR_CLK_OFF|sjaCDR_CBP|sjaCDR_PELICAN;
+       can_write((uint8_t)SJACDR,(uint8_t*)&data);
+
+       // Single acceptance filter, reset mode
+       data=sjaMOD_AFM|sjaMOD_RM;
+       can_write((uint8_t)SJAMOD,(uint8_t*)&data);
+
+       // Enabling all interrupt sources
+       data=sjaENABLE_INTERRUPTS;
+       can_write((uint8_t)SJAIER,(uint8_t*)&data);
+
+       // Accept all messages
+       data=0xFF;
+       can_write((uint8_t)SJAAMR0,(uint8_t*)&data);
+       can_write((uint8_t)SJAAMR0+1,(uint8_t*)&data);
+       can_write((uint8_t)SJAAMR0+2,(uint8_t*)&data);
+       can_write((uint8_t)SJAAMR0+3,(uint8_t*)&data);
+
+       data=sjaCMR_CDO;
+       can_write((uint8_t)SJACMR,(uint8_t*)&data);
+
+       return 0;
+}
diff --git a/embedded/app/usbcan/can/can.h b/embedded/app/usbcan/can/can.h
new file mode 100644 (file)
index 0000000..4dacadf
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef        SJA1000_CAN_H
+#define SJA1000_CAN_H
+
+#include <stdio.h>
+#include <string.h>
+#include <cpu_def.h>
+#include <system_def.h>
+#include <lt_timer.h>
+#include <local_config.h>
+#include <usb/usbdebug.h>
+#include <usb/usb.h>
+#include <usb/lpc.h>
+#include <usb/usb_srq.h>
+#include <mem_loc.h>
+#include <hal_machperiph.h>
+
+
+#include "main.h"
+#include "sja1000p.h"
+/* can.h
+ * Header file for the Linux CAN-bus driver.
+ * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
+ * Rewritten for new CAN queues by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.3  17 Jun 2004
+ */
+
+ /*
+               Delay for synchronization with peripheral (SJA1000)
+ */
+       #define SJA1000_CLK (24000000)  /* XTAL frequency */
+       #define SJA1000_PRESC (2)       /* embedded prescaler */
+       #define SJA1000_CCLK (SJA1000_CLK/SJA1000_PRESC)        /* SJA core frequency */
+       #define SJA1000_SCLK (PCLK/SJA1000_CCLK)        /* Clock count to synchronize with LPC */
+
+       #define SJA1000_DELAY(void)     \
+                       ({ \
+                               volatile int delay; \
+                               for (delay=0;delay<SJA1000_SCLK;delay++) \
+                                       IO0SET=0; \
+                       })
+       #define SJA1000_INIT_DELAY(void)        \
+                       ({ \
+                               volatile int delay; \
+                               for (delay=0;delay<20*SJA1000_SCLK;delay++) \
+                                       IO0SET=0; \
+                       })
+
+/**
+ * struct can_baudparams_t - datatype for calling CONF_BAUDPARAMS IOCTL
+ * @flags: reserved for additional flags for chip configuration, should be written -1 or 0
+ * @baudrate: baud rate in Hz
+ * @sjw: synchronization jump width (0-3) prescaled clock cycles
+ * @sampl_pt: sample point in % (0-100) sets (TSEG1+1)/(TSEG1+TSEG2+2) ratio
+ *
+ * The structure is used to configure new set of parameters into CAN controller chip.
+ * If default value of some field should be preserved, fill field by value -1.
+ */
+struct can_baudparams_t {
+       long flags;
+       long baudrate;
+       long sjw;
+       long sample_pt;
+};
+
+extern int can_init();
+extern int can_read(uint8_t address,uint8_t *data);
+extern int can_write(uint8_t address,uint8_t *data);
+
+#endif /* SJA1000_CAN_H */
diff --git a/embedded/app/usbcan/can/can_queue.h b/embedded/app/usbcan/can/can_queue.h
new file mode 100644 (file)
index 0000000..42eeef4
--- /dev/null
@@ -0,0 +1,809 @@
+/* can_queue.h - CAN queues and message passing infrastructure 
+ * Linux CAN-bus device driver.
+ * Written by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.3  17 Jun 2004
+ */
+
+#ifndef _CAN_QUEUE_H
+#define _CAN_QUEUE_H
+
+#include "./canmsg.h"
+#include "./constants.h"
+#include "./can_sysdep.h"
+
+/**
+ * struct canque_slot_t - one CAN message slot in the CAN FIFO queue 
+ * @next: pointer to the next/younger slot
+ * @slot_flags: space for flags and optional command describing action
+ *     associated with slot data
+ * @msg: space for one CAN message
+ *
+ * This structure is used to store CAN messages in the CAN FIFO queue.
+ */
+ struct canque_slot_t {
+       struct canque_slot_t *next;
+       unsigned long slot_flags;
+       struct canmsg_t msg;
+};
+
+#define CAN_SLOTF_CMD  0x00ff  /*  */
+
+/**
+ * struct canque_fifo_t - CAN FIFO queue representation
+ * @fifo_flags: this field holds global flags describing state of the FIFO.
+ *     %CAN_FIFOF_ERROR is set when some error condition occurs.
+ *     %CAN_FIFOF_ERR2BLOCK defines, that error should lead to the FIFO block state.
+ *     %CAN_FIFOF_BLOCK state blocks insertion of the next messages. 
+ *     %CAN_FIFOF_OVERRUN attempt to acquire new slot, when FIFO is full. 
+ *     %CAN_FIFOF_FULL indicates FIFO full state. 
+ *     %CAN_FIFOF_EMPTY indicates no allocated slot in the FIFO.
+ *     %CAN_FIFOF_DEAD condition indication. Used when FIFO is beeing destroyed.
+ * @error_code: futher description of error condition
+ * @head: pointer to the FIFO head, oldest slot
+ * @tail: pointer to the location, where pointer to newly inserted slot
+ *     should be added
+ * @flist: pointer to list of the free slots associated with queue
+ * @entry: pointer to the memory allocated for the list slots.
+ * @fifo_lock: the lock to ensure atomicity of slot manipulation operations.
+ * @slotsnr:  number of allocated slots
+ *
+ * This structure represents CAN FIFO queue. It is implemented as 
+ * a single linked list of slots prepared for processing. The empty slots
+ * are stored in single linked list (@flist).
+ */
+struct canque_fifo_t {
+       unsigned long fifo_flags;
+       unsigned long error_code;
+       struct canque_slot_t *head;     /* points to the oldest entry */
+       struct canque_slot_t **tail;    /* points to NULL pointer for chaining */
+       struct canque_slot_t *flist;    /* points the first entry in the free list */
+       struct canque_slot_t *entry;    /* points to first allocated entry */
+       can_spinlock_t fifo_lock;       /* can_spin_lock_irqsave / can_spin_unlock_irqrestore */
+       int    slotsnr;
+};
+
+#define CAN_FIFOF_DESTROY_b    15
+#define CAN_FIFOF_ERROR_b      14
+#define CAN_FIFOF_ERR2BLOCK_b  13
+#define CAN_FIFOF_BLOCK_b      12
+#define CAN_FIFOF_OVERRUN_b    11
+#define CAN_FIFOF_FULL_b       10
+#define CAN_FIFOF_EMPTY_b      9
+#define CAN_FIFOF_DEAD_b       8
+#define CAN_FIFOF_INACTIVE_b   7
+#define CAN_FIFOF_FREEONEMPTY_b        6
+#define CAN_FIFOF_READY_b      5
+#define CAN_FIFOF_NOTIFYPEND_b 4
+#define CAN_FIFOF_RTL_MEM_b    3
+
+#define CAN_FIFOF_DESTROY      (1<<CAN_FIFOF_DESTROY_b)
+#define CAN_FIFOF_ERROR                (1<<CAN_FIFOF_ERROR_b)
+#define CAN_FIFOF_ERR2BLOCK    (1<<CAN_FIFOF_ERR2BLOCK_b)
+#define CAN_FIFOF_BLOCK                (1<<CAN_FIFOF_BLOCK_b)
+#define CAN_FIFOF_OVERRUN      (1<<CAN_FIFOF_OVERRUN_b)
+#define CAN_FIFOF_FULL         (1<<CAN_FIFOF_FULL_b)
+#define CAN_FIFOF_EMPTY                (1<<CAN_FIFOF_EMPTY_b)
+#define CAN_FIFOF_DEAD         (1<<CAN_FIFOF_DEAD_b)
+#define CAN_FIFOF_INACTIVE     (1<<CAN_FIFOF_INACTIVE_b)
+#define CAN_FIFOF_FREEONEMPTY  (1<<CAN_FIFOF_FREEONEMPTY_b)
+#define CAN_FIFOF_READY                (1<<CAN_FIFOF_READY_b)
+#define CAN_FIFOF_NOTIFYPEND    (1<<CAN_FIFOF_NOTIFYPEND_b)
+#define CAN_FIFOF_RTL_MEM       (1<<CAN_FIFOF_RTL_MEM_b)
+
+#define canque_fifo_test_fl(fifo,fifo_fl) \
+  test_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
+#define canque_fifo_set_fl(fifo,fifo_fl) \
+  set_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
+#define canque_fifo_clear_fl(fifo,fifo_fl) \
+  clear_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
+#define canque_fifo_test_and_set_fl(fifo,fifo_fl) \
+  test_and_set_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
+#define canque_fifo_test_and_clear_fl(fifo,fifo_fl) \
+  test_and_clear_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
+
+
+/**
+ * canque_fifo_get_inslot - allocate slot for the input of one CAN message 
+ * @fifo: pointer to the FIFO structure
+ * @slotp: pointer to location to store pointer to the allocated slot.
+ * @cmd: optional command associated with allocated slot.
+ *
+ * Return Value: The function returns negative value if there is no
+ *     free slot in the FIFO queue.
+ */
+static inline
+int canque_fifo_get_inslot(struct canque_fifo_t *fifo, struct canque_slot_t **slotp, int cmd)
+{
+       can_spin_irqflags_t flags;
+       struct canque_slot_t *slot;
+       can_spin_lock_irqsave(&fifo->fifo_lock, flags);
+       /* get the first free slot slot from flist */
+       if(!(slot=fifo->flist)) {
+               canque_fifo_set_fl(fifo,OVERRUN);
+               canque_fifo_set_fl(fifo,FULL);
+               can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
+               *slotp=NULL;
+               return -1;
+       }
+       /* adjust free slot list */
+       if(!(fifo->flist=slot->next))
+               canque_fifo_set_fl(fifo,FULL);
+       can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
+       *slotp=slot;
+       slot->slot_flags=cmd&CAN_SLOTF_CMD;
+       return 1;
+}
+
+/**
+ * canque_fifo_put_inslot - releases slot to further processing
+ * @fifo: pointer to the FIFO structure
+ * @slot: pointer to the slot previously acquired by canque_fifo_get_inslot().
+ *
+ * Return Value: The nonzero return value indicates, that the queue was empty
+ *     before call to the function. The caller should wake-up output side of the queue.
+ */
+static inline
+int canque_fifo_put_inslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
+{
+       int ret;
+       can_spin_irqflags_t flags;
+       slot->next=NULL;
+       can_spin_lock_irqsave(&fifo->fifo_lock, flags);
+       if(*fifo->tail) can_printk(KERN_CRIT "canque_fifo_put_inslot: fifo->tail != NULL\n");
+       *fifo->tail=slot;
+       fifo->tail=&slot->next;
+       ret=0;
+       if(canque_fifo_test_and_clear_fl(fifo,EMPTY))
+         ret=CAN_FIFOF_EMPTY;  /* Fifo has been empty before put */
+       if(canque_fifo_test_and_clear_fl(fifo,INACTIVE))
+         ret=CAN_FIFOF_INACTIVE; /* Fifo has been empty before put */
+       can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
+       return ret;
+}
+
+/**
+ * canque_fifo_abort_inslot - release and abort slot
+ * @fifo: pointer to the FIFO structure
+ * @slot: pointer to the slot previously acquired by canque_fifo_get_inslot().
+ *
+ * Return Value: The nonzero value indicates, that fifo was full
+ */
+static inline
+int canque_fifo_abort_inslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
+{
+       int ret=0;
+       can_spin_irqflags_t flags;
+       can_spin_lock_irqsave(&fifo->fifo_lock, flags);
+       slot->next=fifo->flist;
+       fifo->flist=slot;
+       if(canque_fifo_test_and_clear_fl(fifo,FULL))
+               ret=CAN_FIFOF_FULL;
+       can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
+       return ret;
+}
+
+/**
+ * canque_fifo_test_outslot - test and get ready slot from the FIFO
+ * @fifo: pointer to the FIFO structure
+ * @slotp: pointer to location to store pointer to the oldest slot from the FIFO.
+ *
+ * Return Value: The negative value indicates, that queue is empty.
+ *     The positive or zero value represents command stored into slot by
+ *     the call to the function canque_fifo_get_inslot().
+ *     The successfully acquired FIFO output slot has to be released by
+ *     the call canque_fifo_free_outslot() or canque_fifo_again_outslot().
+ */
+static inline
+int canque_fifo_test_outslot(struct canque_fifo_t *fifo, struct canque_slot_t **slotp)
+{
+       can_spin_irqflags_t flags;
+       int cmd;
+       struct canque_slot_t *slot;
+       can_spin_lock_irqsave(&fifo->fifo_lock, flags);
+       if(!(slot=fifo->head)){;
+               canque_fifo_set_fl(fifo,EMPTY);
+               can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
+               *slotp=NULL;
+               return -1;
+       }
+       if(!(fifo->head=slot->next))
+               fifo->tail=&fifo->head;
+       can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
+
+       *slotp=slot;
+       cmd=slot->slot_flags;
+       return cmd&CAN_SLOTF_CMD;
+}
+
+
+/**
+ * canque_fifo_free_outslot - free processed FIFO slot
+ * @fifo: pointer to the FIFO structure
+ * @slot: pointer to the slot previously acquired by canque_fifo_test_outslot().
+ *
+ * Return Value: The returned value informs about FIFO state change.
+ *     The mask %CAN_FIFOF_FULL indicates, that the FIFO was full before
+ *     the function call. The mask %CAN_FIFOF_EMPTY informs, that last ready slot
+ *     has been processed.
+ */
+static inline
+int canque_fifo_free_outslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
+{
+       int ret=0;
+       can_spin_irqflags_t flags;
+       can_spin_lock_irqsave(&fifo->fifo_lock, flags);
+       slot->next=fifo->flist;
+       fifo->flist=slot;
+       if(canque_fifo_test_and_clear_fl(fifo,FULL))
+               ret=CAN_FIFOF_FULL;
+       if(!(fifo->head)){
+               canque_fifo_set_fl(fifo,EMPTY);
+               ret|=CAN_FIFOF_EMPTY;
+       }
+       can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
+       return ret;
+}
+
+/**
+ * canque_fifo_again_outslot - interrupt and postpone processing of the slot
+ * @fifo: pointer to the FIFO structure
+ * @slot: pointer to the slot previously acquired by canque_fifo_test_outslot().
+ *
+ * Return Value: The function cannot fail..
+ */
+static inline
+int canque_fifo_again_outslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
+{
+       can_spin_irqflags_t flags;
+       can_spin_lock_irqsave(&fifo->fifo_lock, flags);
+       if(!(slot->next=fifo->head))
+               fifo->tail=&slot->next;
+       fifo->head=slot;
+       can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
+       return 1;
+}
+
+int canque_fifo_flush_slots(struct canque_fifo_t *fifo);
+
+int canque_fifo_init_slots(struct canque_fifo_t *fifo);
+
+#define CANQUEUE_PRIO_NR  3
+
+/* Forward declarations for external types */
+struct msgobj_t;
+struct canchip_t;
+
+/**
+ * struct canque_edge_t - CAN message delivery subsystem graph edge
+ * @fifo: place where primitive @struct canque_fifo_t FIFO is located.
+ * @filtid: the possible CAN message identifiers filter.
+ * @filtmask: the filter mask, the comparison considers only
+ *     @filtid bits corresponding to set bits in the @filtmask field.
+ * @inpeers: the lists of all peers FIFOs connected by their
+ *     input side (@inends) to the same terminal (@struct canque_ends_t).
+ * @outpeers: the lists of all peers FIFOs connected by their
+ *     output side (@outends) to the same terminal (@struct canque_ends_t).
+ * @activepeers: the lists of peers FIFOs connected by their
+ *     output side (@outends) to the same terminal (@struct canque_ends_t)
+ *     with same priority and active state.
+ * @inends: the pointer to the FIFO input side terminal (@struct canque_ends_t).
+ * @outends: the pointer to the FIFO output side terminal (@struct canque_ends_t).
+ * @edge_used: the atomic usage counter, mainly used for safe destruction of the edge.
+ * @edge_prio: the assigned queue priority from the range 0 to %CANQUEUE_PRIO_NR-1
+ * @edge_num: edge sequential number intended for debugging purposes only
+ * @pending_peers: edges with pending delayed events (RTL->Linux calls)
+ * @pending_inops: bitmask of pending operations
+ * @pending_outops: bitmask of pending operations
+ *
+ * This structure represents one direction connection from messages source 
+ * (@inends) to message consumer (@outends) fifo ends hub. The edge contains
+ * &struct canque_fifo_t for message fifo implementation.
+ */
+struct canque_edge_t {
+       struct canque_fifo_t fifo;
+       unsigned long filtid;
+       unsigned long filtmask;
+       struct list_head inpeers;
+       struct list_head outpeers;
+       struct list_head activepeers;
+       struct canque_ends_t *inends;
+       struct canque_ends_t *outends;
+       atomic_t edge_used;
+       int edge_prio;
+       int edge_num;
+    #ifdef CAN_WITH_RTL
+       struct list_head pending_peers;
+       unsigned long pending_inops;
+       unsigned long pending_outops;
+    #endif /*CAN_WITH_RTL*/
+};
+
+/**
+ * struct canque_ends_t - CAN message delivery subsystem graph vertex (FIFO ends)
+ * @ends_flags: this field holds flags describing state of the ENDS structure.
+ * @active: the array of the lists of active edges directed to the ends structure
+ *     with ready messages. The array is indexed by the edges priorities. 
+ * @idle: the list of the edges directed to the ends structure with empty FIFOs.
+ * @inlist: the list of outgoing edges input sides.
+ * @outlist: the list of all incoming edges output sides. Each of there edges
+ *     is listed on one of @active or @idle lists.
+ * @ends_lock: the lock synchronizing operations between threads accessing
+ *     same ends structure.
+ * @notify: pointer to notify procedure. The next state changes are notified.
+ *     %CANQUEUE_NOTIFY_EMPTY (out->in call) - all slots are processed by FIFO out side. 
+ *     %CANQUEUE_NOTIFY_SPACE (out->in call) - full state negated => there is space for new message.
+ *     %CANQUEUE_NOTIFY_PROC  (in->out call) - empty state negated => out side is requested to process slots.
+ *     %CANQUEUE_NOTIFY_NOUSR (both) - notify, that the last user has released the edge usage
+ *             called with some lock to prevent edge disappear.
+ *     %CANQUEUE_NOTIFY_DEAD  (both) - edge is in progress of deletion.
+ *     %CANQUEUE_NOTIFY_ATACH (both) - new edge has been attached to end.
+ *     %CANQUEUE_NOTIFY_FILTCH (out->in call) - edge filter rules changed
+ *     %CANQUEUE_NOTIFY_ERROR  (out->in call) - error in messages processing.
+ * @context: space to store ends user specific information
+ * @endinfo: space to store some other ends usage specific informations
+ *     mainly for waking-up by the notify calls.
+ * @dead_peers: used to chain ends wanting for postponed destruction
+ *
+ * Structure represents place to connect edges to for CAN communication entity.
+ * The zero, one or more incoming and outgoing edges can be connected to
+ * this structure.
+ */
+struct canque_ends_t {
+       unsigned long ends_flags;
+       struct list_head active[CANQUEUE_PRIO_NR];
+       struct list_head idle;
+       struct list_head inlist;
+       struct list_head outlist;
+       can_spinlock_t ends_lock;       /* can_spin_lock_irqsave / can_spin_unlock_irqrestore */
+       void (*notify)(struct canque_ends_t *qends, struct canque_edge_t *qedge, int what);
+       void *context;
+       union {
+               struct {
+                       wait_queue_head_t readq;
+                       wait_queue_head_t writeq;
+                       wait_queue_head_t emptyq;
+                   #ifdef CAN_ENABLE_KERN_FASYNC
+                       struct fasync_struct *fasync;
+                   #endif /*CAN_ENABLE_KERN_FASYNC*/
+               } fileinfo;
+           #ifdef CAN_WITH_RTL
+               struct {
+                       rtl_spinlock_t rtl_lock;
+                       rtl_wait_t rtl_readq;
+                       atomic_t   rtl_readq_age;
+                       rtl_wait_t rtl_writeq;
+                       atomic_t   rtl_writeq_age;
+                       rtl_wait_t rtl_emptyq;
+                       atomic_t   rtl_emptyq_age;
+                       unsigned long pend_flags;
+               } rtlinfo;
+           #endif /*CAN_WITH_RTL*/
+               struct {
+                       struct msgobj_t *msgobj;
+                       struct canchip_t *chip;
+                   #ifndef CAN_WITH_RTL
+                       wait_queue_head_t daemonq;
+                   #else /*CAN_WITH_RTL*/
+                       pthread_t worker_thread;
+                   #endif /*CAN_WITH_RTL*/
+               } chipinfo;
+       } endinfo;
+       struct list_head dead_peers;
+};
+
+#define CANQUEUE_NOTIFY_EMPTY  1 /* out -> in - all slots are processed by FIFO out side */
+#define CANQUEUE_NOTIFY_SPACE  2 /* out -> in - full state negated => there is space for new message */
+#define CANQUEUE_NOTIFY_PROC   3 /* in -> out - empty state negated => out side is requested to process slots */
+#define CANQUEUE_NOTIFY_NOUSR  4 /* called with some lock to prevent edge disappear */
+#define CANQUEUE_NOTIFY_DEAD   5 /*  */
+#define CANQUEUE_NOTIFY_DEAD_WANTED 6 /*  */
+#define CANQUEUE_NOTIFY_ATTACH 7 /*  */
+#define CANQUEUE_NOTIFY_FILTCH 8 /* filter changed */
+#define CANQUEUE_NOTIFY_ERROR      0x10000 /* error notifiers */
+#define CANQUEUE_NOTIFY_ERRTX_PREP 0x11001 /* tx preparation error */
+#define CANQUEUE_NOTIFY_ERRTX_SEND 0x11002 /* tx send error */
+#define CANQUEUE_NOTIFY_ERRTX_BUS  0x11003 /* tx bus error */
+
+#define CAN_ENDSF_DEAD   (1<<0)
+#define CAN_ENDSF_MEM_RTL (1<<1)
+
+/**
+ * canque_notify_inends - request to send notification to the input ends
+ * @qedge: pointer to the edge structure
+ * @what: notification type
+ */
+static inline
+void canque_notify_inends(struct canque_edge_t *qedge, int what)
+{
+       if(qedge->inends)
+               if(qedge->inends->notify)
+                       qedge->inends->notify(qedge->inends,qedge,what);
+}
+
+/**
+ * canque_notify_outends - request to send notification to the output ends
+ * @qedge: pointer to the edge structure
+ * @what: notification type
+ */
+static inline
+void canque_notify_outends(struct canque_edge_t *qedge, int what)
+{
+       if(qedge->outends)
+               if(qedge->outends->notify)
+                       qedge->outends->notify(qedge->outends,qedge,what);
+}
+
+/**
+ * canque_notify_bothends - request to send notification to the both ends
+ * @qedge: pointer to the edge structure
+ * @what: notification type
+ */
+static inline
+void canque_notify_bothends(struct canque_edge_t *qedge, int what)
+{
+       canque_notify_inends(qedge, what);
+       canque_notify_outends(qedge, what);
+}
+
+/**
+ * canque_activate_edge - mark output end of the edge as active
+ * @qedge: pointer to the edge structure
+ * @inends: input side of the edge
+ *
+ * Function call moves output side of the edge from idle onto active edges
+ * list. This function has to be called with edge reference count held.
+ * that is same as for most of other edge functions.
+ */
+static inline
+void canque_activate_edge(struct canque_ends_t *inends, struct canque_edge_t *qedge)
+{
+       can_spin_irqflags_t flags;
+       struct canque_ends_t *outends;
+       if(qedge->edge_prio>=CANQUEUE_PRIO_NR)
+               qedge->edge_prio=CANQUEUE_PRIO_NR-1;
+       if((outends=qedge->outends)){
+               can_spin_lock_irqsave(&outends->ends_lock, flags);
+               can_spin_lock(&qedge->fifo.fifo_lock);
+               if(!canque_fifo_test_fl(&qedge->fifo,EMPTY)){
+                       list_del(&qedge->activepeers);
+                       list_add_tail(&qedge->activepeers,&outends->active[qedge->edge_prio]);
+               }
+               can_spin_unlock(&qedge->fifo.fifo_lock);
+               can_spin_unlock_irqrestore(&outends->ends_lock, flags);
+       }
+}
+
+/**
+ * canque_filtid2internal - converts message ID and filter flags into internal format
+ * @id: CAN message 11 or 29 bit identifier
+ * @filtflags: CAN message flags
+ *
+ * This function maps message ID and %MSG_RTR, %MSG_EXT and %MSG_LOCAL into one 32 bit number
+ */
+static inline
+unsigned int canque_filtid2internal(unsigned long id, int filtflags)
+{
+       filtflags &= MSG_RTR|MSG_EXT|MSG_LOCAL;
+       filtflags += filtflags&MSG_RTR;
+       return (id&MSG_ID_MASK) | (filtflags<<28);
+}
+
+int canque_get_inslot(struct canque_ends_t *qends,
+       struct canque_edge_t **qedgep, struct canque_slot_t **slotp, int cmd);
+       
+int canque_get_inslot4id(struct canque_ends_t *qends,
+       struct canque_edge_t **qedgep, struct canque_slot_t **slotp,
+       int cmd, unsigned long id, int prio);
+       
+int canque_put_inslot(struct canque_ends_t *qends,
+       struct canque_edge_t *qedge, struct canque_slot_t *slot);
+
+int canque_abort_inslot(struct canque_ends_t *qends,
+       struct canque_edge_t *qedge, struct canque_slot_t *slot);
+
+int canque_filter_msg2edges(struct canque_ends_t *qends, struct canmsg_t *msg);
+
+int canque_test_outslot(struct canque_ends_t *qends,
+       struct canque_edge_t **qedgep, struct canque_slot_t **slotp);
+
+int canque_free_outslot(struct canque_ends_t *qends,
+       struct canque_edge_t *qedge, struct canque_slot_t *slot);
+
+int canque_again_outslot(struct canque_ends_t *qends,
+       struct canque_edge_t *qedge, struct canque_slot_t *slot);
+
+int canque_set_filt(struct canque_edge_t *qedge,
+       unsigned long filtid, unsigned long filtmask, int flags);
+       
+int canque_flush(struct canque_edge_t *qedge);
+
+int canqueue_disconnect_edge(struct canque_edge_t *qedge);
+
+int canqueue_connect_edge(struct canque_edge_t *qedge, struct canque_ends_t *inends, struct canque_ends_t *outends);
+
+int canqueue_ends_init_gen(struct canque_ends_t *qends);
+
+void canqueue_block_inlist(struct canque_ends_t *qends);
+
+void canqueue_block_outlist(struct canque_ends_t *qends);
+
+int canqueue_ends_kill_inlist(struct canque_ends_t *qends, int send_rest);
+
+int canqueue_ends_kill_outlist(struct canque_ends_t *qends);
+
+int canqueue_ends_filt_conjuction(struct canque_ends_t *qends, struct canfilt_t *filt);
+
+int canqueue_ends_flush_inlist(struct canque_ends_t *qends);
+
+int canqueue_ends_flush_outlist(struct canque_ends_t *qends);
+
+/* edge reference and traversal functions */
+
+void canque_edge_do_dead(struct canque_edge_t *edge);
+
+/**
+ * canque_edge_incref - increments edge reference count
+ * @edge: pointer to the edge structure
+ */
+static inline
+void canque_edge_incref(struct canque_edge_t *edge)
+{
+       atomic_inc(&edge->edge_used);
+}
+
+static inline
+can_spin_irqflags_t canque_edge_lock_both_ends(struct canque_ends_t *inends, struct canque_ends_t *outends)
+{
+       can_spin_irqflags_t  flags;
+       if(inends<outends) {
+               can_spin_lock_irqsave(&inends->ends_lock, flags);
+               can_spin_lock(&outends->ends_lock);
+       }else{
+               can_spin_lock_irqsave(&outends->ends_lock, flags);
+               if(outends!=inends) can_spin_lock(&inends->ends_lock);
+       }
+       return flags;   
+}
+
+static inline
+void canque_edge_unlock_both_ends(struct canque_ends_t *inends, struct canque_ends_t *outends, can_spin_irqflags_t flags)
+{
+       if(outends!=inends) can_spin_unlock(&outends->ends_lock);
+       can_spin_unlock_irqrestore(&inends->ends_lock, flags);
+}
+
+/* Non-inlined version of edge reference decrement */
+void __canque_edge_decref(struct canque_edge_t *edge);
+
+static inline
+void __canque_edge_decref_body(struct canque_edge_t *edge)
+{
+       can_spin_irqflags_t flags;
+       int dead_fl=0;
+       struct canque_ends_t *inends=edge->inends;
+       struct canque_ends_t *outends=edge->outends;
+       
+       flags=canque_edge_lock_both_ends(inends, outends);
+       if(atomic_dec_and_test(&edge->edge_used)) {
+               dead_fl=!canque_fifo_test_and_set_fl(&edge->fifo,DEAD);
+               /* Because of former evolution of edge references 
+                  management notify of CANQUEUE_NOTIFY_NOUSR could
+                  be moved to canque_edge_do_dead :-) */
+       }
+       canque_edge_unlock_both_ends(inends, outends, flags);
+       if(dead_fl) canque_edge_do_dead(edge);
+}
+
+#ifndef CAN_HAVE_ARCH_CMPXCHG
+/**
+ * canque_edge_decref - decrements edge reference count
+ * @edge: pointer to the edge structure
+ *
+ * This function has to be called without lock held for both ends of edge.
+ * If reference count drops to 0, function canque_edge_do_dead()
+ * is called.
+ */
+static inline
+void canque_edge_decref(struct canque_edge_t *edge)
+{
+       __canque_edge_decref_body(edge);
+}
+#else
+static inline
+void canque_edge_decref(struct canque_edge_t *edge)
+{
+       int x, y;
+       
+        x = atomic_read(&edge->edge_used);
+        do{
+               if(x<=1)
+                       return __canque_edge_decref(edge);
+               y=x;
+               /* This code strongly depends on the definition of atomic_t !!!! */
+               /* x=cmpxchg(&edge->edge_used, x, x-1); */
+               /* Next alternative could be more portable */
+               x=__cmpxchg(&edge->edge_used, x, x-1, sizeof(atomic_t));
+               /* If even this does not help, comment out CAN_HAVE_ARCH_CMPXCHG in can_sysdep.h */
+       } while(x!=y);
+}
+#endif
+
+static inline
+struct canque_edge_t *canque_first_inedge(struct canque_ends_t *qends)
+{
+       can_spin_irqflags_t flags;
+       struct list_head *entry;
+       struct canque_edge_t *edge;
+       
+       can_spin_lock_irqsave(&qends->ends_lock, flags);
+       entry=qends->inlist.next;
+    skip_dead:
+       if(entry != &qends->inlist) {
+               edge=list_entry(entry,struct canque_edge_t,inpeers);
+               if(canque_fifo_test_fl(&edge->fifo,DEAD)) {
+                       entry=entry->next;
+                       goto skip_dead;
+               }
+               canque_edge_incref(edge);
+       } else {
+               edge=NULL;
+       }
+       can_spin_unlock_irqrestore(&qends->ends_lock, flags);
+       return edge;
+}
+
+
+static inline
+struct canque_edge_t *canque_next_inedge(struct canque_ends_t *qends, struct canque_edge_t *edge)
+{
+       can_spin_irqflags_t flags;
+       struct list_head *entry;
+       struct canque_edge_t *next;
+       
+       can_spin_lock_irqsave(&qends->ends_lock, flags);
+       entry=edge->inpeers.next;
+    skip_dead:
+       if(entry != &qends->inlist) {
+               next=list_entry(entry,struct canque_edge_t,inpeers);
+               if(canque_fifo_test_fl(&edge->fifo,DEAD)) {
+                       entry=entry->next;
+                       goto skip_dead;
+               }
+               canque_edge_incref(next);
+       } else {
+               next=NULL;
+       }
+       can_spin_unlock_irqrestore(&qends->ends_lock, flags);
+       canque_edge_decref(edge);
+       return next;
+}
+
+#define canque_for_each_inedge(qends, edge) \
+           for(edge=canque_first_inedge(qends);edge;edge=canque_next_inedge(qends, edge))
+
+static inline
+struct canque_edge_t *canque_first_outedge(struct canque_ends_t *qends)
+{
+       can_spin_irqflags_t flags;
+       struct list_head *entry;
+       struct canque_edge_t *edge;
+       
+       can_spin_lock_irqsave(&qends->ends_lock, flags);
+       entry=qends->outlist.next;
+    skip_dead:
+       if(entry != &qends->outlist) {
+               edge=list_entry(entry,struct canque_edge_t,outpeers);
+               if(canque_fifo_test_fl(&edge->fifo,DEAD)) {
+                       entry=entry->next;
+                       goto skip_dead;
+               }
+               canque_edge_incref(edge);
+       } else {
+               edge=NULL;
+       }
+       can_spin_unlock_irqrestore(&qends->ends_lock, flags);
+       return edge;
+}
+
+
+static inline
+struct canque_edge_t *canque_next_outedge(struct canque_ends_t *qends, struct canque_edge_t *edge)
+{
+       can_spin_irqflags_t flags;
+       struct list_head *entry;
+       struct canque_edge_t *next;
+       
+       can_spin_lock_irqsave(&qends->ends_lock, flags);
+       entry=edge->outpeers.next;
+    skip_dead:
+       if(entry != &qends->outlist) {
+               next=list_entry(entry,struct canque_edge_t,outpeers);
+               if(canque_fifo_test_fl(&edge->fifo,DEAD)) {
+                       entry=entry->next;
+                       goto skip_dead;
+               }
+               canque_edge_incref(next);
+       } else {
+               next=NULL;
+       }
+       can_spin_unlock_irqrestore(&qends->ends_lock, flags);
+       canque_edge_decref(edge);
+       return next;
+}
+
+#define canque_for_each_outedge(qends, edge) \
+           for(edge=canque_first_outedge(qends);edge;edge=canque_next_outedge(qends, edge))
+
+/* Linux kernel specific functions */
+
+int canque_fifo_init_kern(struct canque_fifo_t *fifo, int slotsnr);
+
+int canque_fifo_done_kern(struct canque_fifo_t *fifo);
+
+struct canque_edge_t *canque_new_edge_kern(int slotsnr);
+
+int canque_get_inslot4id_wait_kern(struct canque_ends_t *qends,
+       struct canque_edge_t **qedgep, struct canque_slot_t **slotp,
+       int cmd, unsigned long id, int prio);
+
+int canque_get_outslot_wait_kern(struct canque_ends_t *qends,
+       struct canque_edge_t **qedgep, struct canque_slot_t **slotp);
+
+int canque_sync_wait_kern(struct canque_ends_t *qends, struct canque_edge_t *qedge);
+
+int canqueue_ends_init_kern(struct canque_ends_t *qends);
+
+int canqueue_ends_dispose_kern(struct canque_ends_t *qends, int sync);
+
+void canqueue_ends_dispose_postpone(struct canque_ends_t *qends);
+
+void canqueue_kern_initialize(void);
+
+#ifdef CAN_WITH_RTL
+
+extern struct tasklet_struct canque_dead_tl;   /*publication required only for RTL*/
+
+/* RT-Linux specific functions and variables */
+
+extern int canqueue_rtl_irq;
+
+extern unsigned long canqueue_rtl2lin_pend;
+
+#define CAN_RTL2LIN_PEND_DEAD_b 0
+
+void canqueue_rtl_initialize(void);
+void canqueue_rtl_done(void);
+
+int canqueue_rtl2lin_check_and_pend(struct canque_ends_t *qends,
+                        struct canque_edge_t *qedge, int what);
+
+struct canque_edge_t *canque_new_edge_rtl(int slotsnr);
+
+void canque_dispose_edge_rtl(struct canque_edge_t *qedge);
+
+int canque_get_inslot4id_wait_rtl(struct canque_ends_t *qends,
+       struct canque_edge_t **qedgep, struct canque_slot_t **slotp,
+       int cmd, unsigned long id, int prio);
+
+int canque_get_outslot_wait_rtl(struct canque_ends_t *qends,
+       struct canque_edge_t **qedgep, struct canque_slot_t **slotp);
+
+int canque_sync_wait_rtl(struct canque_ends_t *qends, struct canque_edge_t *qedge);
+
+void canque_ends_free_rtl(struct canque_ends_t *qends);
+
+int canqueue_ends_init_rtl(struct canque_ends_t *qends);
+
+int canqueue_ends_dispose_rtl(struct canque_ends_t *qends, int sync);
+
+#else /*CAN_WITH_RTL*/
+
+static inline int canqueue_rtl2lin_check_and_pend(struct canque_ends_t *qends,
+                       struct canque_edge_t *qedge, int what) { return 0; }
+
+#endif /*CAN_WITH_RTL*/
+
+
+#endif /*_CAN_QUEUE_H*/
diff --git a/embedded/app/usbcan/can/can_sysdep.h b/embedded/app/usbcan/can/can_sysdep.h
new file mode 100644 (file)
index 0000000..5a3b86c
--- /dev/null
@@ -0,0 +1,226 @@
+/* can_sysdep.h - hides differences between individual Linux kernel 
+ *                versions and RT extensions 
+ * Linux CAN-bus device driver.
+ * Written by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.3  17 Jun 2004
+ */
+
+#ifndef _CAN_SYSDEP_H
+#define _CAN_SYSDEP_H
+
+#ifdef CAN_WITH_RTL
+#include <rtl.h>
+#include <rtl_sync.h>
+#include <rtl_core.h>
+#include <rtl_mutex.h>
+#include <rtl_sched.h>
+#include <time.h>
+#endif /*CAN_WITH_RTL*/
+
+/*#define __NO_VERSION__*/
+/*#include <linux/module.h>*/
+
+#include <linux/version.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/fs.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/errno.h>
+
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "lincan_config.h"
+
+/*optional features*/
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0))
+#define CAN_ENABLE_KERN_FASYNC
+#ifdef CONFIG_PCI
+#define CAN_ENABLE_PCI_SUPPORT
+#endif
+#ifdef CONFIG_OC_LINCANVME
+#define CAN_ENABLE_VME_SUPPORT
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
+#include <linux/malloc.h>
+#else
+#include <linux/slab.h>
+#endif
+
+#ifdef CAN_ENABLE_PCI_SUPPORT
+#include "linux/pci.h"
+#endif /*CAN_ENABLE_PCI_SUPPORT*/
+
+/* Next is not sctrictly correct, because of 2.3.0, 2.3.1, 2.3.2
+   kernels need next definitions  too */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,19)) /* may need correction */
+  #define wait_queue_head_t struct wait_queue *
+  #define wait_queue_t      struct wait_queue
+  #define init_waitqueue_head(queue_head) (*queue_head=NULL)
+  #define init_waitqueue_entry(qentry,qtask) \
+                        (qentry->next=NULL,qentry->task=qtask)
+  #define DECLARE_WAIT_QUEUE_HEAD(name) \
+        struct wait_queue * name=NULL
+  #define DECLARE_WAITQUEUE(wait, current) \
+        struct wait_queue wait = { current, NULL }
+  #define init_MUTEX(sem) (*sem=MUTEX)
+  #define DECLARE_MUTEX(name) struct semaphore name=MUTEX
+#endif /* 2.2.19 */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) && !defined(DECLARE_TASKLET)
+  #define tasklet_struct tq_struct
+  #define DECLARE_TASKLET(_name, _func, _data) \
+                struct tq_struct _name = { sync: 0, routine: _func, data: (void*)_data }
+
+  /* void tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long), unsigned long data); */
+  #define tasklet_init(_tasklet, _func, _data) \
+    do{ \
+       /* (_tasklet)->next=NULL; */ \
+       /* Above not needed for 2.2.x and buggy for 2.4.x */ \
+       (_tasklet)->sync=0; \
+       (_tasklet)->routine=_func; \
+       (_tasklet)->data=(void*)_data; \
+    }while(0)
+
+  /* void tasklet_schedule(struct tasklet_struct *t) */
+  #define tasklet_schedule(_tasklet) \
+    do{ \
+       queue_task(_tasklet,&tq_immediate); \
+       mark_bh(IMMEDIATE_BH); \
+    }while(0)
+
+  /* void tasklet_kill(struct tasklet_struct *t); */
+  #define tasklet_kill(_tasklet) \
+                synchronize_irq()
+
+#endif /* 2.4.0 */
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,7)) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+
+#define MINOR_NR \
+       (MINOR(file->f_dentry->d_inode->i_rdev))
+
+#else /* Linux kernel < 2.5.7 or >= 2.6.0 */
+
+#define MINOR_NR \
+       (minor(file->f_dentry->d_inode->i_rdev))
+
+#endif /* Linux kernel < 2.5.7 or >= 2.6.0 */
+
+#ifndef CAN_WITH_RTL
+#if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68)) && !defined(IRQ_RETVAL))
+  typedef void can_irqreturn_t;
+  #define CAN_IRQ_NONE
+  #define CAN_IRQ_HANDLED
+  #define CAN_IRQ_RETVAL(x)
+#else /* <=2.5.67 */
+  typedef irqreturn_t can_irqreturn_t;
+  #define CAN_IRQ_NONE    IRQ_NONE
+  #define CAN_IRQ_HANDLED IRQ_HANDLED
+  #define CAN_IRQ_RETVAL  IRQ_RETVAL
+#endif /* <=2.5.67 */
+#else /*CAN_WITH_RTL*/
+  typedef int can_irqreturn_t;
+  #define CAN_IRQ_NONE        0
+  #define CAN_IRQ_HANDLED     1
+  #define CAN_IRQ_RETVAL(x)   ((x) != 0)
+#endif /*CAN_WITH_RTL*/
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,33))
+   #define can_synchronize_irq(irqnum) synchronize_irq()
+#else /* >=2.5.33 */
+   #define can_synchronize_irq synchronize_irq
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
+  #define del_timer_sync del_timer
+#endif /* <2.4.0 */
+
+#ifdef __HAVE_ARCH_CMPXCHG
+  #define CAN_HAVE_ARCH_CMPXCHG
+#endif
+
+#ifndef CAN_WITH_RTL
+/* Standard LINUX kernel */
+
+#define can_spinlock_t             spinlock_t
+#define can_spin_irqflags_t        unsigned long
+#define can_spin_lock              spin_lock
+#define can_spin_unlock            spin_unlock
+#define can_spin_lock_irqsave      spin_lock_irqsave
+#define can_spin_unlock_irqrestore spin_unlock_irqrestore
+#define can_spin_lock_init         spin_lock_init
+
+#ifndef DEFINE_SPINLOCK
+#define CAN_DEFINE_SPINLOCK(x)     can_spinlock_t x = SPIN_LOCK_UNLOCKED
+#else /*DEFINE_SPINLOCK*/
+#define CAN_DEFINE_SPINLOCK        DEFINE_SPINLOCK
+#endif /*DEFINE_SPINLOCK*/
+
+#if defined(CONFIG_PREEMPT) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+#define can_preempt_disable        preempt_disable
+#define can_preempt_enable         preempt_enable
+#else /*CONFIG_PREEMPT*/
+#define can_preempt_disable()      do { } while (0)
+#define can_preempt_enable()       do { } while (0)
+#endif /*CONFIG_PREEMPT*/
+
+#define can_enable_irq             enable_irq
+#define can_disable_irq            disable_irq
+
+#define can_printk                 printk
+
+/* CAN message timestamp source, it is called from interrupt context */
+#define can_gettimeofday do_gettimeofday
+
+#else /*CAN_WITH_RTL*/
+
+#define can_spinlock_t             rtl_spinlock_t
+#define can_spin_irqflags_t        rtl_irqstate_t
+#define can_spin_lock              rtl_spin_lock
+#define can_spin_unlock            rtl_spin_unlock
+#define can_spin_lock_irqsave      rtl_spin_lock_irqsave
+#define can_spin_unlock_irqrestore rtl_spin_unlock_irqrestore
+#define can_spin_lock_init         rtl_spin_lock_init
+
+#define CAN_DEFINE_SPINLOCK(x)     can_spinlock_t x = SPIN_LOCK_UNLOCKED
+
+#define can_preempt_disable()      do { } while (0)
+#define can_preempt_enable()       do { } while (0)
+
+#define can_enable_irq             rtl_hard_enable_irq
+#define can_disable_irq            rtl_hard_disable_irq
+
+#define can_printk                 rtl_printf
+
+/*
+ * terrible hack to test rtl_file private_data concept, ugh !!!
+ * this would result in crash on architectures,  where 
+ * sizeof(int) < sizeof(void *)
+ */
+#define can_set_rtl_file_private_data(fptr, p) do{ fptr->f_minor=(long)(p); } while(0)
+#define can_get_rtl_file_private_data(fptr) ((void*)((fptr)->f_minor))
+
+extern can_spinlock_t can_irq_manipulation_lock;
+
+/* CAN message timestamp source, it is called from interrupt context */
+#define can_gettimeofday(ptr) do {\
+         struct timespec temp_timespec;\
+         clock_gettime(CLOCK_REALTIME,&temp_timespec);\
+         ptr->tv_usec=temp_timespec.tv_nsec/1000;\
+         ptr->tv_sec=temp_timespec.tv_sec;\
+       } while(0)
+
+#endif /*CAN_WITH_RTL*/
+
+#endif /*_CAN_SYSDEP_H*/
diff --git a/embedded/app/usbcan/can/can_sysless.h b/embedded/app/usbcan/can/can_sysless.h
new file mode 100644 (file)
index 0000000..af3d703
--- /dev/null
@@ -0,0 +1,537 @@
+/* can_sysdep.h - hides differences between individual Linux kernel
+ *                versions and RT extensions
+ * Linux CAN-bus device driver.
+ * Written by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.3  17 Jun 2004
+ */
+
+#ifndef _CAN_SYSDEP_H
+#define _CAN_SYSDEP_H
+
+#ifdef CAN_WITH_RTL
+#include <rtl.h>
+#include <rtl_sync.h>
+#include <rtl_core.h>
+#include <rtl_mutex.h>
+#include <rtl_sched.h>
+#include <time.h>
+#endif /*CAN_WITH_RTL*/
+
+#include <cpu_def.h>
+#include <malloc.h>
+
+// typedef unsigned long atomic_t;
+typedef struct { volatile int counter; } atomic_t;
+
+#define mb()   __memory_barrier()
+
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr:       the pointer to the member.
+ * @type:      the type of the container struct this is embedded in.
+ * @member:    the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({                     \
+       const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
+       (type *)( (char *)__mptr - offsetof(type,member) );})
+
+
+/*#define __NO_VERSION__*/
+/*#include <linux/module.h>*/
+
+// #include <linux/version.h>
+// #include <linux/wait.h>
+// #include <linux/list.h>
+// #include <linux/fs.h>
+// #include <linux/ioport.h>
+// #include <linux/delay.h>
+// #include <linux/sched.h>
+// #include <linux/interrupt.h>
+// #include <asm/errno.h>
+//
+// #include <asm/io.h>
+// #include <asm/atomic.h>
+// #include <asm/irq.h>
+// #include <asm/uaccess.h>
+
+// #include "lincan_config.h"
+
+/*optional features*/
+// #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0))
+// #define CAN_ENABLE_KERN_FASYNC
+// #ifdef CONFIG_PCI
+// #define CAN_ENABLE_PCI_SUPPORT
+// #endif
+// #ifdef CONFIG_OC_LINCANVME
+// #define CAN_ENABLE_VME_SUPPORT
+// #endif
+// #endif
+
+// #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
+// #include <linux/malloc.h>
+// #else
+// #include <linux/slab.h>
+// #endif
+
+// #ifdef CAN_ENABLE_PCI_SUPPORT
+// #include "linux/pci.h"
+// #endif /*CAN_ENABLE_PCI_SUPPORT*/
+
+/* Next is not sctrictly correct, because of 2.3.0, 2.3.1, 2.3.2
+   kernels need next definitions  too */
+// #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,19)) /* may need correction */
+   #define wait_queue_head_t struct wait_queue *
+   #define wait_queue_t      struct wait_queue
+   #define init_waitqueue_head(queue_head) (*queue_head=NULL)
+  #define init_waitqueue_entry(qentry,qtask) \
+                        (qentry->next=NULL,qentry->task=qtask)
+  #define DECLARE_WAIT_QUEUE_HEAD(name) \
+        struct wait_queue * name=NULL
+  #define DECLARE_WAITQUEUE(wait, current) \
+        struct wait_queue wait = { current, NULL }
+//   #define init_MUTEX(sem) (*sem=MUTEX)
+//   #define DECLARE_MUTEX(name) struct semaphore name=MUTEX
+// #endif /* 2.2.19 */
+
+// #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) && !defined(DECLARE_TASKLET)
+//   #define tasklet_struct tq_struct
+/*  #define DECLARE_TASKLET(_name, _func, _data) \
+                struct tq_struct _name = { sync: 0, routine: _func, data: (void*)_data }*/
+//
+//   /* void tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long), unsigned long data); */
+/*   #define tasklet_init(_tasklet, _func, _data) \
+    do{ \
+       (_tasklet)->sync=0; \
+       (_tasklet)->routine=_func; \
+       (_tasklet)->data=(void*)_data; \
+    }while(0)*/
+//
+//   /* void tasklet_schedule(struct tasklet_struct *t) */
+/*  #define tasklet_schedule(_tasklet) \
+    do{ \
+       queue_task(_tasklet,&tq_immediate); \
+       mark_bh(IMMEDIATE_BH); \
+    }while(0)*/
+//
+//   /* void tasklet_kill(struct tasklet_struct *t); */
+/*  #define tasklet_kill(_tasklet) \
+                synchronize_irq()*/
+//
+// #endif /* 2.4.0 */
+
+
+// #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,7)) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+
+#define MINOR_NR \
+       (MINOR(file->f_dentry->d_inode->i_rdev))
+
+// #else /* Linux kernel < 2.5.7 or >= 2.6.0 */
+//
+/*#define MINOR_NR \
+       (minor(file->f_dentry->d_inode->i_rdev))*/
+//
+// #endif /* Linux kernel < 2.5.7 or >= 2.6.0 */
+
+// #ifndef CAN_WITH_RTL
+// #if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68)) && !defined(IRQ_RETVAL))
+  typedef void can_irqreturn_t;
+  #define CAN_IRQ_NONE
+  #define CAN_IRQ_HANDLED
+  #define CAN_IRQ_RETVAL(x)
+// #else /* <=2.5.67 */
+//   typedef irqreturn_t can_irqreturn_t;
+//   #define CAN_IRQ_NONE    IRQ_NONE
+//   #define CAN_IRQ_HANDLED IRQ_HANDLED
+//   #define CAN_IRQ_RETVAL  IRQ_RETVAL
+// #endif /* <=2.5.67 */
+// #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+/*  #define CAN_IRQ_HANDLER_ARGS(irq_number, dev_id) \
+               int irq_number, void *dev_id, struct pt_regs *regs*/
+// #else /* < 2.6.19 */
+  #define CAN_IRQ_HANDLER_ARGS(irq_number, dev_id) \
+               int irq_number, void *dev_id
+// #endif /* < 2.6.19 */
+// #else /*CAN_WITH_RTL*/
+//   typedef int can_irqreturn_t;
+//   #define CAN_IRQ_NONE        0
+//   #define CAN_IRQ_HANDLED     1
+//   #define CAN_IRQ_RETVAL(x)   ((x) != 0)
+/*  #define CAN_IRQ_HANDLER_ARGS(irq_number, dev_id) \
+               int irq_number, void *dev_id, struct pt_regs *regs*/
+// #endif /*CAN_WITH_RTL*/
+
+// #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,33))
+//    #define can_synchronize_irq(irqnum) synchronize_irq()
+// #else /* >=2.5.33 */
+   #define can_synchronize_irq synchronize_irq
+// #endif
+
+// #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
+//   #define del_timer_sync del_timer
+// #endif /* <2.4.0 */
+
+// #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9))
+   typedef unsigned long can_ioptr_t;
+   #define can_ioptr2ulong(ioaddr) ((unsigned long)(ioaddr))
+   #define can_ulong2ioptr(addr)   ((unsigned long)(addr))
+   #define can_inb(ioaddr) inb(ioaddr)
+   #define can_outb(data,ioaddr) outb(data,ioaddr)
+   #define can_inw(ioaddr) inb(ioaddr)
+   #define can_outw(data,ioaddr) outb(data,ioaddr)
+   #define can_inl(ioaddr) inb(ioaddr)
+   #define can_outl(data,ioaddr) outb(data,ioaddr)
+// #else /* >=2.6.9 */
+//    typedef void __iomem * can_ioptr_t;
+//    #define can_ioptr2ulong(ioaddr) ((unsigned long __force)(ioaddr))
+//    #define can_ulong2ioptr(addr)   ((can_ioptr_t)(addr))
+//    #define can_inb(ioaddr) inb(can_ioptr2ulong(ioaddr))
+//    #define can_outb(data,ioaddr) outb(data,can_ioptr2ulong(ioaddr))
+//    #define can_inw(ioaddr) inb(can_ioptr2ulong(ioaddr))
+//    #define can_outw(data,ioaddr) outb(data,can_ioptr2ulong(ioaddr))
+//    #define can_inl(ioaddr) inb(can_ioptr2ulong(ioaddr))
+//    #define can_outl(data,ioaddr) outb(data,can_ioptr2ulong(ioaddr))
+// #endif
+
+#define can_readb  readb
+#define can_writeb writeb
+#define can_readw  readw
+#define can_writew writew
+#define can_readl  readl
+#define can_writel writel
+
+#define can_ioport2ioptr can_ulong2ioptr
+
+#ifdef __HAVE_ARCH_CMPXCHG
+  #define CAN_HAVE_ARCH_CMPXCHG
+#endif
+
+// #ifndef CAN_WITH_RTL
+/* Standard LINUX kernel */
+
+#define can_spinlock_t             long
+#define can_spin_irqflags_t        unsigned long
+#define can_spin_lock(lock)        cli()
+#define can_spin_unlock(lock)      sti()
+#define can_spin_lock_irqsave(lock,flags)      save_and_cli(flags)
+#define can_spin_unlock_irqrestore(lock,flags) restore_flags(flags)
+#define can_spin_lock_init         can_splck_init
+
+#define CAN_DEFINE_SPINLOCK(x)     can_spinlock_t x = 0
+
+static inline
+void can_splck_init(can_spinlock_t *x)
+{
+       *x=0;
+}
+
+// #if !defined(CONFIG_PREEMPT_RT) && ( defined(CONFIG_PREEMPT) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) )
+// #define can_preempt_disable        preempt_disable
+// #define can_preempt_enable         preempt_enable
+// #else /*CONFIG_PREEMPT*/
+#define can_preempt_disable()      do { } while (0)
+#define can_preempt_enable()       do { } while (0)
+// #endif /*CONFIG_PREEMPT*/
+
+// #define can_enable_irq             sti()
+// #define can_disable_irq            cli()
+#define can_enable_irq(var)           (var=1)
+#define can_disable_irq(var)          (var=0)
+
+#define can_printk                 printf
+#define KERN_CRIT
+#define KERN_ERR
+
+/// LINUX src: include/asm-arm/bitops.h
+
+#define set_bit ____atomic_set_bit
+#define clear_bit ____atomic_clear_bit
+#define change_bit ____atomic_change_bit
+#define test_and_set_bit ____atomic_test_and_set_bit
+#define test_and_clear_bit ____atomic_test_and_clear_bit
+#define test_and_change_bit ____atomic_test_and_change_bit
+#define raw_local_irq_save(flags) save_and_cli(flags);
+#define raw_local_irq_restore(flags) restore_flags(flags);
+/*
+ * These functions are the basis of our bit ops.
+ *
+ * First, the atomic bitops. These use native endian.
+ */
+static inline void ____atomic_set_bit(unsigned int bit, volatile unsigned long *p)
+{
+       unsigned long flags;
+       unsigned long mask = 1UL << (bit & 31);
+
+       p += bit >> 5;
+
+       raw_local_irq_save(flags);
+       *p |= mask;
+       raw_local_irq_restore(flags);
+}
+
+static inline void ____atomic_clear_bit(unsigned int bit, volatile unsigned long *p)
+{
+       unsigned long flags;
+       unsigned long mask = 1UL << (bit & 31);
+
+       p += bit >> 5;
+
+       raw_local_irq_save(flags);
+       *p &= ~mask;
+       raw_local_irq_restore(flags);
+}
+
+static inline void ____atomic_change_bit(unsigned int bit, volatile unsigned long *p)
+{
+       unsigned long flags;
+       unsigned long mask = 1UL << (bit & 31);
+
+       p += bit >> 5;
+
+       raw_local_irq_save(flags);
+       *p ^= mask;
+       raw_local_irq_restore(flags);
+}
+
+static inline int
+____atomic_test_and_set_bit(unsigned int bit, volatile unsigned long *p)
+{
+       unsigned long flags;
+       unsigned int res;
+       unsigned long mask = 1UL << (bit & 31);
+
+       p += bit >> 5;
+
+       raw_local_irq_save(flags);
+       res = *p;
+       *p = res | mask;
+       raw_local_irq_restore(flags);
+
+       return res & mask;
+}
+
+static inline int
+____atomic_test_and_clear_bit(unsigned int bit, volatile unsigned long *p)
+{
+       unsigned long flags;
+       unsigned int res;
+       unsigned long mask = 1UL << (bit & 31);
+
+       p += bit >> 5;
+
+       raw_local_irq_save(flags);
+       res = *p;
+       *p = res & ~mask;
+       raw_local_irq_restore(flags);
+
+       return res & mask;
+}
+
+static inline int
+____atomic_test_and_change_bit(unsigned int bit, volatile unsigned long *p)
+{
+       unsigned long flags;
+       unsigned int res;
+       unsigned long mask = 1UL << (bit & 31);
+
+       p += bit >> 5;
+
+       raw_local_irq_save(flags);
+       res = *p;
+       *p = res ^ mask;
+       raw_local_irq_restore(flags);
+
+       return res & mask;
+}
+
+/// LINUX src: include/asm-arm/atomic.h
+
+#define atomic_read(v) ((v)->counter)
+
+#define atomic_set(v,i)        (((v)->counter) = (i))
+
+static inline int atomic_add_return(int i, atomic_t *v)
+{
+       unsigned long flags;
+       int val;
+
+       raw_local_irq_save(flags);
+       val = v->counter;
+       v->counter = val += i;
+       raw_local_irq_restore(flags);
+
+       return val;
+}
+
+static inline int atomic_sub_return(int i, atomic_t *v)
+{
+       unsigned long flags;
+       int val;
+
+       raw_local_irq_save(flags);
+       val = v->counter;
+       v->counter = val -= i;
+       raw_local_irq_restore(flags);
+
+       return val;
+}
+
+static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
+{
+       int ret;
+       unsigned long flags;
+
+       raw_local_irq_save(flags);
+       ret = v->counter;
+       if (ret == old)
+               v->counter = new;
+       raw_local_irq_restore(flags);
+
+       return ret;
+}
+
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+
+static inline int atomic_add_unless(atomic_t *v, int a, int u)
+{
+       int c, old;
+
+       c = atomic_read(v);
+       while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c)
+               c = old;
+       return c != u;
+}
+#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+
+#define atomic_add(i, v)       (void) atomic_add_return(i, v)
+#define atomic_inc(v)          (void) atomic_add_return(1, v)
+#define atomic_sub(i, v)       (void) atomic_sub_return(i, v)
+#define atomic_dec(v)          (void) atomic_sub_return(1, v)
+
+#define atomic_inc_and_test(v) (atomic_add_return(1, v) == 0)
+#define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0)
+#define atomic_inc_return(v)    (atomic_add_return(1, v))
+#define atomic_dec_return(v)    (atomic_sub_return(1, v))
+#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0)
+
+#define atomic_add_negative(i,v) (atomic_add_return(i, v) < 0)
+
+/* Atomic operations are already serializing on ARM */
+#define smp_mb__before_atomic_dec()    barrier()
+#define smp_mb__after_atomic_dec()     barrier()
+#define smp_mb__before_atomic_inc()    barrier()
+#define smp_mb__after_atomic_inc()     barrier()
+
+/// LINUX src: include/linux/interrupt.h
+
+#define ATOMIC_INIT(i) { (i) }
+
+/* Tasklets --- multithreaded analogue of BHs.
+
+   Main feature differing them of generic softirqs: tasklet
+   is running only on one CPU simultaneously.
+
+   Main feature differing them of BHs: different tasklets
+   may be run simultaneously on different CPUs.
+
+   Properties:
+   * If tasklet_schedule() is called, then tasklet is guaranteed
+     to be executed on some cpu at least once after this.
+   * If the tasklet is already scheduled, but its excecution is still not
+     started, it will be executed only once.
+   * If this tasklet is already running on another CPU (or schedule is called
+     from tasklet itself), it is rescheduled for later.
+   * Tasklet is strictly serialized wrt itself, but not
+     wrt another tasklets. If client needs some intertask synchronization,
+     he makes it with spinlocks.
+ */
+
+struct tasklet_struct
+{
+       struct tasklet_struct *next;
+       unsigned long state;
+       atomic_t count;
+       void (*func)(unsigned long);
+       unsigned long data;
+};
+
+#define DECLARE_TASKLET(name, func, data) \
+struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data }
+
+#define DECLARE_TASKLET_DISABLED(name, func, data) \
+struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(1), func, data }
+
+/* CAN message timestamp source, it is called from interrupt context */
+//#define can_gettimeofday do_gettimeofday
+
+/// from linux/timer.h
+
+struct tvec_t_base_s;
+
+struct timer_list {
+       struct list_head entry;
+       unsigned long expires;
+
+       void (*function)(unsigned long);
+       unsigned long data;
+
+       struct tvec_t_base_s *base;
+#ifdef CONFIG_TIMER_STATS
+       void *start_site;
+       char start_comm[16];
+       int start_pid;
+#endif
+};
+
+static inline void udelay(long time)
+{
+       volatile long ticks=(time * CCLK) / 2000000;
+       do{
+               ticks--;
+       }
+       while(ticks>0);
+}
+
+// #else /*CAN_WITH_RTL*/
+//
+// #define can_spinlock_t             long
+// #define can_spin_irqflags_t        unsigned long
+// #define can_spin_lock              save_and_cli
+// #define can_spin_unlock            restore_flags
+// #define can_spin_lock_irqsave      save_and_cli
+// #define can_spin_unlock_irqrestore restore_flags
+// #define can_spin_lock_init         can_splck_init
+//
+// #define CAN_DEFINE_SPINLOCK(x)     can_spinlock_t x = 0
+//
+// #define can_preempt_disable()      do { } while (0)
+// #define can_preempt_enable()       do { } while (0)
+//
+// #define can_enable_irq             sti
+// #define can_disable_irq            cli
+//
+// #define can_printk                 rtl_printf
+//
+// /*
+//  * terrible hack to test rtl_file private_data concept, ugh !!!
+//  * this would result in crash on architectures,  where
+//  * sizeof(int) < sizeof(void *)
+//  */
+// #define can_set_rtl_file_private_data(fptr, p) do{ fptr->f_minor=(long)(p); } while(0)
+// #define can_get_rtl_file_private_data(fptr) ((void*)((fptr)->f_minor))
+//
+// extern can_spinlock_t can_irq_manipulation_lock;
+//
+// /* CAN message timestamp source, it is called from interrupt context */
+/*#define can_gettimeofday(ptr) do {\
+         struct timespec temp_timespec;\
+         clock_gettime(CLOCK_REALTIME,&temp_timespec);\
+         ptr->tv_usec=temp_timespec.tv_nsec/1000;\
+         ptr->tv_sec=temp_timespec.tv_sec;\
+       } while(0)*/
+//
+// #endif /*CAN_WITH_RTL*/
+
+#endif /*_CAN_SYSDEP_H*/
diff --git a/embedded/app/usbcan/can/canmsg.h b/embedded/app/usbcan/can/canmsg.h
new file mode 100644 (file)
index 0000000..779f68c
--- /dev/null
@@ -0,0 +1,136 @@
+/* canmsg.h - common kernel-space and user-space CAN message structure
+ * Linux CAN-bus device driver.
+ * Written by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.3  17 Jun 2004
+ */
+
+#ifndef _CANMSG_T_H
+#define _CANMSG_T_H
+
+#ifdef __KERNEL__
+
+#include <linux/time.h>
+#include <linux/types.h>
+
+#else /* __KERNEL__ */
+
+#include <sys/time.h>
+#include <sys/types.h>
+
+#endif /* __KERNEL__ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 
+ * CAN_MSG_VERSION_2 enables new canmsg_t layout compatible with
+ * can4linux project from http://www.port.de/
+ * 
+ */
+#define CAN_MSG_VERSION_2
+
+/* Number of data bytes in one CAN message */
+#define CAN_MSG_LENGTH 8
+
+#ifdef CAN_MSG_VERSION_2
+
+typedef struct timeval canmsg_tstamp_t ;
+
+typedef unsigned long canmsg_id_t;
+
+/**
+ * struct canmsg_t - structure representing CAN message
+ * @flags:  message flags
+ *      %MSG_RTR .. message is Remote Transmission Request,
+ *     %MSG_EXT .. message with extended ID, 
+ *      %MSG_OVR .. indication of queue overflow condition,
+ *     %MSG_LOCAL .. message originates from this node.
+ * @cob:    communication object number (not used)
+ * @id:     ID of CAN message
+ * @timestamp: not used
+ * @length: length of used data
+ * @data:   data bytes buffer
+ *
+ * Header: canmsg.h
+ */
+struct canmsg_t {
+       int             flags;
+       int             cob;
+       canmsg_id_t     id;
+       canmsg_tstamp_t timestamp;
+       unsigned short  length;
+       unsigned char   data[CAN_MSG_LENGTH];
+};
+
+#else /*CAN_MSG_VERSION_2*/
+#ifndef PACKED
+#define PACKED __attribute__((packed))
+#endif
+/* Old, deprecated version of canmsg_t structure */
+struct canmsg_t {
+       short           flags;
+       int             cob;
+       canmsg_id_t     id;
+       unsigned long   timestamp;
+       unsigned int    length;
+       unsigned char   data[CAN_MSG_LENGTH];
+} PACKED;
+#endif /*CAN_MSG_VERSION_2*/
+
+typedef struct canmsg_t canmsg_t;
+
+/**
+ * struct canfilt_t - structure for acceptance filter setup
+ * @flags:  message flags
+ *      %MSG_RTR .. message is Remote Transmission Request,
+ *     %MSG_EXT .. message with extended ID, 
+ *      %MSG_OVR .. indication of queue overflow condition,
+ *     %MSG_LOCAL .. message originates from this node.
+ *     there are corresponding mask bits
+ *     %MSG_RTR_MASK, %MSG_EXT_MASK, %MSG_LOCAL_MASK.
+ *     %MSG_PROCESSLOCAL enables local messages processing in the
+ *     combination with global setting
+ * @queid:  CAN queue identification in the case of the multiple
+ *         queues per one user (open instance)
+ * @cob:    communication object number (not used)
+ * @id:     selected required value of cared ID id bits
+ * @mask:   select bits significand for the comparation;
+ *          1 .. take care about corresponding ID bit, 0 .. don't care
+ *
+ * Header: canmsg.h
+ */
+struct canfilt_t {
+       int             flags;
+       int             queid;
+       int             cob;
+       canmsg_id_t     id;
+       canmsg_id_t     mask;
+};
+
+typedef struct canfilt_t canfilt_t;
+
+/* Definitions to use for canmsg_t and canfilt_t flags */
+#define MSG_RTR   (1<<0)
+#define MSG_OVR   (1<<1)
+#define MSG_EXT   (1<<2)
+#define MSG_LOCAL (1<<3)
+/* If you change above lines, check canque_filtid2internal function */
+
+/* Additional definitions used for canfilt_t only */
+#define MSG_FILT_MASK_SHIFT   8
+#define MSG_RTR_MASK   (MSG_RTR<<MSG_FILT_MASK_SHIFT)
+#define MSG_EXT_MASK   (MSG_EXT<<MSG_FILT_MASK_SHIFT)
+#define MSG_LOCAL_MASK (MSG_LOCAL<<MSG_FILT_MASK_SHIFT)
+#define MSG_PROCESSLOCAL (MSG_OVR<<MSG_FILT_MASK_SHIFT)
+
+/* Can message ID mask */
+#define MSG_ID_MASK ((1l<<29)-1)
+
+#ifdef __cplusplus
+} /* extern "C"*/
+#endif
+
+#endif /*_CANMSG_T_H*/
diff --git a/embedded/app/usbcan/can/constants.h b/embedded/app/usbcan/can/constants.h
new file mode 100644 (file)
index 0000000..8ba9ba4
--- /dev/null
@@ -0,0 +1,113 @@
+/* constants.h
+ * Header file for the Linux CAN-bus driver.
+ * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
+ * Rewritten for new CAN queues by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.3  17 Jun 2004
+ */
+
+#ifndef __CONSTANTS_H__
+#define __CONSTANTS_H__
+
+/* Device name as it will appear in /proc/devices */
+#define DEVICE_NAME "can"
+
+/* Branch of the driver */
+#define CAN_DRV_BRANCH (('L'<<24)|('I'<<16)|('N'<<8)|'C')
+
+/* Version of the driver */
+#define CAN_DRV_VER_MAJOR 0
+#define CAN_DRV_VER_MINOR 3
+#define CAN_DRV_VER_PATCH 3
+#define CAN_DRV_VER ((CAN_DRV_VER_MAJOR<<16) | (CAN_DRV_VER_MINOR<<8) | CAN_DRV_VER_PATCH)
+
+/* Default driver major number, see /usr/src/linux/Documentation/devices.txt */
+#define CAN_MAJOR 91
+
+/* Definition of the maximum number of concurrent supported hardware boards,
+ * chips per board, total number of chips, interrupts and message objects.
+ * Obviously there are no 32 different interrupts, but each chip can have its
+ * own interrupt so we have to check for it MAX_IRQ == MAX_TOT_CHIPS times.
+ */
+#define MAX_HW_CARDS 8
+#define MAX_HW_CHIPS 4
+#define MAX_TOT_CHIPS (MAX_HW_CHIPS*MAX_HW_CARDS)
+#define MAX_TOT_CHIPS_STR 32   /* must be explicit for MODULE_PARM */
+#define MAX_IRQ 32
+#define MAX_MSGOBJS 32
+#define MAX_TOT_MSGOBJS (MAX_TOT_CHIPS*MAX_MSGOBJS)
+#define MAX_BUF_LENGTH 64
+//#define MAX_BUF_LENGTH 4
+
+
+/* These flags can be used for the msgobj_t structure flags data entry */
+#define MSGOBJ_OPENED_b                   0
+#define MSGOBJ_TX_REQUEST_b       1
+#define MSGOBJ_TX_LOCK_b           2
+#define MSGOBJ_IRQ_REQUEST_b       3
+#define MSGOBJ_WORKER_WAKE_b       4
+#define MSGOBJ_FILTCH_REQUEST_b    5
+#define MSGOBJ_RX_MODE_b           6
+#define MSGOBJ_RX_MODE_EXT_b       7
+#define MSGOBJ_TX_PENDING_b        8
+
+#define MSGOBJ_OPENED              (1<<MSGOBJ_OPENED_b)
+#define MSGOBJ_TX_REQUEST          (1<<MSGOBJ_TX_REQUEST_b)
+#define MSGOBJ_TX_LOCK             (1<<MSGOBJ_TX_LOCK_b)
+#define MSGOBJ_IRQ_REQUEST         (1<<MSGOBJ_IRQ_REQUEST_b)
+#define MSGOBJ_WORKER_WAKE         (1<<MSGOBJ_WORKER_WAKE_b)
+#define MSGOBJ_FILTCH_REQUEST      (1<<MSGOBJ_FILTCH_REQUEST_b)
+#define MSGOBJ_RX_MODE             (1<<MSGOBJ_RX_MODE_b)
+#define MSGOBJ_RX_MODE_EXT         (1<<MSGOBJ_RX_MODE_EXT_b)
+#define MSGOBJ_TX_PENDING          (1<<MSGOBJ_TX_PENDING_b)
+
+#define can_msgobj_test_fl(obj,obj_fl) \
+  test_bit(MSGOBJ_##obj_fl##_b,&(obj)->obj_flags)
+#define can_msgobj_set_fl(obj,obj_fl) \
+  set_bit(MSGOBJ_##obj_fl##_b,&(obj)->obj_flags)
+#define can_msgobj_clear_fl(obj,obj_fl) \
+  clear_bit(MSGOBJ_##obj_fl##_b,&(obj)->obj_flags)
+#define can_msgobj_test_and_set_fl(obj,obj_fl) \
+  test_and_set_bit(MSGOBJ_##obj_fl##_b,&(obj)->obj_flags)
+#define can_msgobj_test_and_clear_fl(obj,obj_fl) \
+  test_and_clear_bit(MSGOBJ_##obj_fl##_b,&(obj)->obj_flags)
+
+
+/* These flags can be used for the canchip_t structure flags data entry */
+#define CHIP_ATTACHED    (1<<0)  /* chip is attached to HW, release_chip() has to be called */
+#define CHIP_CONFIGURED  (1<<1)  /* chip is configured and prepared for communication */
+#define CHIP_SEGMENTED   (1<<2)  /* segmented access, ex: i82527 with 16 byte window*/
+#define CHIP_IRQ_SETUP   (1<<3)  /* IRQ handler has been set */
+#define CHIP_IRQ_PCI     (1<<4)  /* chip is on PCI board and uses PCI interrupt  */
+#define CHIP_IRQ_VME     (1<<5)  /* interrupt is VME bus and requires VME bridge */
+#define CHIP_IRQ_CUSTOM  (1<<6)  /* custom interrupt provided by board or chip code */
+#define CHIP_IRQ_FAST    (1<<7)  /* interrupt handler only schedules postponed processing */
+
+#define CHIP_MAX_IRQLOOP 1000
+
+/* System independent defines of IRQ handled state */
+#define CANCHIP_IRQ_NONE     0
+#define CANCHIP_IRQ_HANDLED  1
+#define CANCHIP_IRQ_ACCEPTED 2
+#define CANCHIP_IRQ_STUCK    3
+
+/* These flags can be used for the candevices_t structure flags data entry */
+#define CANDEV_PROGRAMMABLE_IRQ (1<<0)
+#define CANDEV_IO_RESERVED     (1<<1)
+
+/* Next flags are specific for struct canuser_t applications connection */
+#define CANUSER_RTL_CLIENT      (1<<0)
+#define CANUSER_RTL_MEM         (1<<1)
+#define CANUSER_DIRECT          (1<<2)
+
+
+enum timing_BTR1 {
+       MAX_TSEG1 = 15,
+       MAX_TSEG2 = 7
+};
+
+/* Flags for baud_rate function */
+#define BTR1_SAM (1<<1)
+
+#endif
diff --git a/embedded/app/usbcan/can/devcommon.h b/embedded/app/usbcan/can/devcommon.h
new file mode 100644 (file)
index 0000000..837ffb6
--- /dev/null
@@ -0,0 +1,15 @@
+/* devcommon.h - common device code
+ * Linux CAN-bus device driver.
+ * New CAN queues by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.3  17 Jun 2004
+ */
+
+#include "./canmsg.h"
+#include "./can_sysdep.h"
+#include "./constants.h"
+#include "./can_queue.h"
+
+int canqueue_ends_init_chip(struct canque_ends_t *qends, struct canchip_t *chip, struct msgobj_t *obj);
+int canqueue_ends_done_chip(struct canque_ends_t *qends);
diff --git a/embedded/app/usbcan/can/errno-base.h b/embedded/app/usbcan/can/errno-base.h
new file mode 100755 (executable)
index 0000000..6511597
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef _ASM_GENERIC_ERRNO_BASE_H
+#define _ASM_GENERIC_ERRNO_BASE_H
+
+#define        EPERM            1      /* Operation not permitted */
+#define        ENOENT           2      /* No such file or directory */
+#define        ESRCH            3      /* No such process */
+#define        EINTR            4      /* Interrupted system call */
+#define        EIO              5      /* I/O error */
+#define        ENXIO            6      /* No such device or address */
+#define        E2BIG            7      /* Argument list too long */
+#define        ENOEXEC          8      /* Exec format error */
+#define        EBADF            9      /* Bad file number */
+#define        ECHILD          10      /* No child processes */
+#define        EAGAIN          11      /* Try again */
+#define        ENOMEM          12      /* Out of memory */
+#define        EACCES          13      /* Permission denied */
+#define        EFAULT          14      /* Bad address */
+#define        ENOTBLK         15      /* Block device required */
+#define        EBUSY           16      /* Device or resource busy */
+#define        EEXIST          17      /* File exists */
+#define        EXDEV           18      /* Cross-device link */
+#define        ENODEV          19      /* No such device */
+#define        ENOTDIR         20      /* Not a directory */
+#define        EISDIR          21      /* Is a directory */
+#define        EINVAL          22      /* Invalid argument */
+#define        ENFILE          23      /* File table overflow */
+#define        EMFILE          24      /* Too many open files */
+#define        ENOTTY          25      /* Not a typewriter */
+#define        ETXTBSY         26      /* Text file busy */
+#define        EFBIG           27      /* File too large */
+#define        ENOSPC          28      /* No space left on device */
+#define        ESPIPE          29      /* Illegal seek */
+#define        EROFS           30      /* Read-only file system */
+#define        EMLINK          31      /* Too many links */
+#define        EPIPE           32      /* Broken pipe */
+#define        EDOM            33      /* Math argument out of domain of func */
+#define        ERANGE          34      /* Math result not representable */
+
+#endif
diff --git a/embedded/app/usbcan/can/errno.h b/embedded/app/usbcan/can/errno.h
new file mode 100755 (executable)
index 0000000..6edbe36
--- /dev/null
@@ -0,0 +1,109 @@
+#ifndef _ASM_GENERIC_ERRNO_H
+#define _ASM_GENERIC_ERRNO_H
+
+#include "./errno-base.h"
+
+#define        EDEADLK         35      /* Resource deadlock would occur */
+#define        ENAMETOOLONG    36      /* File name too long */
+#define        ENOLCK          37      /* No record locks available */
+#define        ENOSYS          38      /* Function not implemented */
+#define        ENOTEMPTY       39      /* Directory not empty */
+#define        ELOOP           40      /* Too many symbolic links encountered */
+#define        EWOULDBLOCK     EAGAIN  /* Operation would block */
+#define        ENOMSG          42      /* No message of desired type */
+#define        EIDRM           43      /* Identifier removed */
+#define        ECHRNG          44      /* Channel number out of range */
+#define        EL2NSYNC        45      /* Level 2 not synchronized */
+#define        EL3HLT          46      /* Level 3 halted */
+#define        EL3RST          47      /* Level 3 reset */
+#define        ELNRNG          48      /* Link number out of range */
+#define        EUNATCH         49      /* Protocol driver not attached */
+#define        ENOCSI          50      /* No CSI structure available */
+#define        EL2HLT          51      /* Level 2 halted */
+#define        EBADE           52      /* Invalid exchange */
+#define        EBADR           53      /* Invalid request descriptor */
+#define        EXFULL          54      /* Exchange full */
+#define        ENOANO          55      /* No anode */
+#define        EBADRQC         56      /* Invalid request code */
+#define        EBADSLT         57      /* Invalid slot */
+
+#define        EDEADLOCK       EDEADLK
+
+#define        EBFONT          59      /* Bad font file format */
+#define        ENOSTR          60      /* Device not a stream */
+#define        ENODATA         61      /* No data available */
+#define        ETIME           62      /* Timer expired */
+#define        ENOSR           63      /* Out of streams resources */
+#define        ENONET          64      /* Machine is not on the network */
+#define        ENOPKG          65      /* Package not installed */
+#define        EREMOTE         66      /* Object is remote */
+#define        ENOLINK         67      /* Link has been severed */
+#define        EADV            68      /* Advertise error */
+#define        ESRMNT          69      /* Srmount error */
+#define        ECOMM           70      /* Communication error on send */
+#define        EPROTO          71      /* Protocol error */
+#define        EMULTIHOP       72      /* Multihop attempted */
+#define        EDOTDOT         73      /* RFS specific error */
+#define        EBADMSG         74      /* Not a data message */
+#define        EOVERFLOW       75      /* Value too large for defined data type */
+#define        ENOTUNIQ        76      /* Name not unique on network */
+#define        EBADFD          77      /* File descriptor in bad state */
+#define        EREMCHG         78      /* Remote address changed */
+#define        ELIBACC         79      /* Can not access a needed shared library */
+#define        ELIBBAD         80      /* Accessing a corrupted shared library */
+#define        ELIBSCN         81      /* .lib section in a.out corrupted */
+#define        ELIBMAX         82      /* Attempting to link in too many shared libraries */
+#define        ELIBEXEC        83      /* Cannot exec a shared library directly */
+#define        EILSEQ          84      /* Illegal byte sequence */
+#define        ERESTART        85      /* Interrupted system call should be restarted */
+#define        ESTRPIPE        86      /* Streams pipe error */
+#define        EUSERS          87      /* Too many users */
+#define        ENOTSOCK        88      /* Socket operation on non-socket */
+#define        EDESTADDRREQ    89      /* Destination address required */
+#define        EMSGSIZE        90      /* Message too long */
+#define        EPROTOTYPE      91      /* Protocol wrong type for socket */
+#define        ENOPROTOOPT     92      /* Protocol not available */
+#define        EPROTONOSUPPORT 93      /* Protocol not supported */
+#define        ESOCKTNOSUPPORT 94      /* Socket type not supported */
+#define        EOPNOTSUPP      95      /* Operation not supported on transport endpoint */
+#define        EPFNOSUPPORT    96      /* Protocol family not supported */
+#define        EAFNOSUPPORT    97      /* Address family not supported by protocol */
+#define        EADDRINUSE      98      /* Address already in use */
+#define        EADDRNOTAVAIL   99      /* Cannot assign requested address */
+#define        ENETDOWN        100     /* Network is down */
+#define        ENETUNREACH     101     /* Network is unreachable */
+#define        ENETRESET       102     /* Network dropped connection because of reset */
+#define        ECONNABORTED    103     /* Software caused connection abort */
+#define        ECONNRESET      104     /* Connection reset by peer */
+#define        ENOBUFS         105     /* No buffer space available */
+#define        EISCONN         106     /* Transport endpoint is already connected */
+#define        ENOTCONN        107     /* Transport endpoint is not connected */
+#define        ESHUTDOWN       108     /* Cannot send after transport endpoint shutdown */
+#define        ETOOMANYREFS    109     /* Too many references: cannot splice */
+#define        ETIMEDOUT       110     /* Connection timed out */
+#define        ECONNREFUSED    111     /* Connection refused */
+#define        EHOSTDOWN       112     /* Host is down */
+#define        EHOSTUNREACH    113     /* No route to host */
+#define        EALREADY        114     /* Operation already in progress */
+#define        EINPROGRESS     115     /* Operation now in progress */
+#define        ESTALE          116     /* Stale NFS file handle */
+#define        EUCLEAN         117     /* Structure needs cleaning */
+#define        ENOTNAM         118     /* Not a XENIX named type file */
+#define        ENAVAIL         119     /* No XENIX semaphores available */
+#define        EISNAM          120     /* Is a named type file */
+#define        EREMOTEIO       121     /* Remote I/O error */
+#define        EDQUOT          122     /* Quota exceeded */
+
+#define        ENOMEDIUM       123     /* No medium found */
+#define        EMEDIUMTYPE     124     /* Wrong medium type */
+#define        ECANCELED       125     /* Operation Canceled */
+#define        ENOKEY          126     /* Required key not available */
+#define        EKEYEXPIRED     127     /* Key has expired */
+#define        EKEYREVOKED     128     /* Key has been revoked */
+#define        EKEYREJECTED    129     /* Key was rejected by service */
+
+/* for robust mutexes */
+#define        EOWNERDEAD      130     /* Owner died */
+#define        ENOTRECOVERABLE 131     /* State not recoverable */
+
+#endif
diff --git a/embedded/app/usbcan/can/finish.h b/embedded/app/usbcan/can/finish.h
new file mode 100644 (file)
index 0000000..87df046
--- /dev/null
@@ -0,0 +1,13 @@
+/* finish.h
+ * Header file for the Linux CAN-bus driver.
+ * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
+ * Rewritten for new CAN queues by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.3  17 Jun 2004
+ */
+
+void msgobj_done(struct msgobj_t *obj);
+void canchip_done(struct canchip_t *chip);
+void candevice_done(struct candevice_t *candev);
+void canhardware_done(struct canhardware_t *candev);
diff --git a/embedded/app/usbcan/can/i82527.h b/embedded/app/usbcan/can/i82527.h
new file mode 100644 (file)
index 0000000..1747396
--- /dev/null
@@ -0,0 +1,177 @@
+/* i82527.h
+ * Header file for the Linux CAN-bus driver.
+ * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
+ * Rewritten for new CAN queues by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.3  17 Jun 2004
+ */
+
+int i82527_enable_configuration(struct canchip_t *chip);
+int i82527_disable_configuration(struct canchip_t *chip);
+int i82527_chip_config(struct canchip_t *chip);
+int i82527_baud_rate(struct canchip_t *chip, int rate, int clock, int sjw, 
+                                               int sampl_pt, int flags);
+int i82527_standard_mask(struct canchip_t *chip, unsigned short code, 
+                                                       unsigned short mask);
+int i82527_extended_mask(struct canchip_t *chip, unsigned long code, 
+                                                       unsigned long mask);
+int i82527_message15_mask(struct canchip_t *chip, unsigned long code, 
+                                                       unsigned long mask);
+int i82527_clear_objects(struct canchip_t *chip);
+int i82527_config_irqs(struct canchip_t *chip, short irqs);
+int i82527_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj);
+int i82527_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj,
+                                                       struct canmsg_t *msg);
+int i82527_send_msg(struct canchip_t *chip, struct msgobj_t *obj,
+                                                       struct canmsg_t *msg);
+int i82527_remote_request(struct canchip_t *chip, struct msgobj_t *obj);
+int i82527_set_btregs(struct canchip_t *chip, unsigned short btr0, 
+                                                       unsigned short btr1);
+int i82527_start_chip(struct canchip_t *chip);
+int i82527_stop_chip(struct canchip_t *chip);
+int i82527_check_tx_stat(struct canchip_t *chip);
+int i82527_irq_handler(int irq, struct canchip_t *chip);
+int i82527_fill_chipspecops(struct canchip_t *chip);
+
+
+#define MSG_OFFSET(object) ((object)*0x10)
+
+#define iCTL 0x00              // Control Register
+#define iSTAT 0x01             // Status Register
+#define iCPU 0x02              // CPU Interface Register
+#define iHSR 0x04              // High Speed Read
+#define iSGM0 0x06             // Standard Global Mask byte 0
+#define iSGM1 0x07
+#define iEGM0 0x08             // Extended Global Mask byte 0
+#define iEGM1 0x09
+#define iEGM2 0x0a
+#define iEGM3 0x0b
+#define i15M0 0x0c             // Message 15 Mask byte 0
+#define i15M1 0x0d
+#define i15M2 0x0e
+#define i15M3 0x0f
+#define iCLK 0x1f              // Clock Out Register
+#define iBUS 0x2f              // Bus Configuration Register
+#define iBT0 0x3f              // Bit Timing Register byte 0
+#define iBT1 0x4f
+#define iIRQ 0x5f              // Interrupt Register
+#define iP1C 0x9f              // Port 1 Register
+#define iP2C 0xaf              // Port 2 Register
+#define iP1I 0xbf              // Port 1 Data In Register
+#define iP2I 0xcf              // Port 2 Data In Register
+#define iP1O 0xdf              // Port 1 Data Out Register
+#define iP2O 0xef              // Port 2 Data Out Register
+#define iSRA 0xff              // Serial Reset Address
+
+#define iMSGCTL0       0x00    /* First Control register */
+#define iMSGCTL1       0x01    /* Second Control register */
+#define iMSGID0                0x02    /* First Byte of Message ID */
+#define iMSGID1                0x03
+#define iMSGID2                0x04
+#define iMSGID3                0x05
+#define iMSGCFG                0x06    /* Message Configuration */
+#define iMSGDAT0       0x07    /* First Data Byte */
+#define iMSGDAT1       0x08
+#define iMSGDAT2       0x09
+#define iMSGDAT3       0x0a
+#define iMSGDAT4       0x0b
+#define iMSGDAT5       0x0c
+#define iMSGDAT6       0x0d
+#define iMSGDAT7       0x0e
+
+/* Control Register (0x00) */
+enum i82527_iCTL {
+       iCTL_INI = 1,           // Initialization
+       iCTL_IE  = 1<<1,        // Interrupt Enable
+       iCTL_SIE = 1<<2,        // Status Interrupt Enable
+       iCTL_EIE = 1<<3,        // Error Interrupt Enable
+       iCTL_CCE = 1<<6         // Change Configuration Enable
+};
+
+/* Status Register (0x01) */
+enum i82527_iSTAT {
+       iSTAT_TXOK = 1<<3,      // Transmit Message Successfully
+       iSTAT_RXOK = 1<<4,      // Receive Message Successfully
+       iSTAT_WAKE = 1<<5,      // Wake Up Status
+       iSTAT_WARN = 1<<6,      // Warning Status
+       iSTAT_BOFF = 1<<7       // Bus Off Status
+};
+
+/* CPU Interface Register (0x02) */
+enum i82527_iCPU {
+       iCPU_CEN = 1,           // Clock Out Enable
+       iCPU_MUX = 1<<2,        // Multiplex
+       iCPU_SLP = 1<<3,        // Sleep
+       iCPU_PWD = 1<<4,        // Power Down Mode
+       iCPU_DMC = 1<<5,        // Divide Memory Clock
+       iCPU_DSC = 1<<6,        // Divide System Clock
+       iCPU_RST = 1<<7         // Hardware Reset Status
+};
+
+/* Clock Out Register (0x1f) */
+enum i82527_iCLK {
+       iCLK_CD0 = 1,           // Clock Divider bit 0
+       iCLK_CD1 = 1<<1,
+       iCLK_CD2 = 1<<2,
+       iCLK_CD3 = 1<<3,
+       iCLK_SL0 = 1<<4,        // Slew Rate bit 0
+       iCLK_SL1 = 1<<5
+};
+
+/* Bus Configuration Register (0x2f) */
+enum i82527_iBUS {
+       iBUS_DR0 = 1,           // Disconnect RX0 Input
+       iBUS_DR1 = 1<<1,        // Disconnect RX1 Input
+       iBUS_DT1 = 1<<3,        // Disconnect TX1 Output
+       iBUS_POL = 1<<5,        // Polarity
+       iBUS_CBY = 1<<6         // Comparator Bypass
+};
+
+#define RESET 1                        // Bit Pair Reset Status
+#define SET 2                  // Bit Pair Set Status
+#define UNCHANGED 3            // Bit Pair Unchanged
+
+/* Message Control Register 0 (Base Address + 0x0) */
+enum i82527_iMSGCTL0 {
+       INTPD_SET = SET,                // Interrupt pending
+       INTPD_RES = RESET,              // No Interrupt pending
+       INTPD_UNC = UNCHANGED,
+       RXIE_SET  = SET<<2,             // Receive Interrupt Enable
+       RXIE_RES  = RESET<<2,           // Receive Interrupt Disable
+       RXIE_UNC  = UNCHANGED<<2,
+       TXIE_SET  = SET<<4,             // Transmit Interrupt Enable
+       TXIE_RES  = RESET<<4,           // Transmit Interrupt Disable
+       TXIE_UNC  = UNCHANGED<<4,
+       MVAL_SET  = SET<<6,             // Message Valid
+       MVAL_RES  = RESET<<6,           // Message Invalid
+       MVAL_UNC  = UNCHANGED<<6
+};
+
+/* Message Control Register 1 (Base Address + 0x01) */
+enum i82527_iMSGCTL1 {
+       NEWD_SET = SET,                 // New Data
+       NEWD_RES = RESET,               // No New Data
+       NEWD_UNC = UNCHANGED,
+       MLST_SET = SET<<2,              // Message Lost
+       MLST_RES = RESET<<2,            // No Message Lost
+       MLST_UNC = UNCHANGED<<2,
+       CPUU_SET = SET<<2,              // CPU Updating
+       CPUU_RES = RESET<<2,            // No CPU Updating
+       CPUU_UNC = UNCHANGED<<2,
+       TXRQ_SET = SET<<4,              // Transmission Request
+       TXRQ_RES = RESET<<4,            // No Transmission Request
+       TXRQ_UNC = UNCHANGED<<4,
+       RMPD_SET = SET<<6,              // Remote Request Pending
+       RMPD_RES = RESET<<6,            // No Remote Request Pending
+       RMPD_UNC = UNCHANGED<<6
+};
+
+/* Message Configuration Register (Base Address + 0x06) */
+enum i82527_iMSGCFG {
+       MCFG_XTD = 1<<2,                // Extended Identifier
+       MCFG_DIR = 1<<3                 // Direction is Transmit
+};
+
+void i82527_seg_write_reg(const struct canchip_t *chip, unsigned char data, unsigned address);
+unsigned i82527_seg_read_reg(const struct canchip_t *chip, unsigned address);
diff --git a/embedded/app/usbcan/can/main.h b/embedded/app/usbcan/can/main.h
new file mode 100644 (file)
index 0000000..23c8ab3
--- /dev/null
@@ -0,0 +1,523 @@
+/* main.h
+ * Header file for the Linux CAN-bus driver.
+ * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
+ * Rewritten for new CAN queues by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.3  17 Jun 2004
+ */
+
+#ifndef MAIN_H
+#define MAIN_H
+
+#include <malloc.h>
+
+#include "./can.h"
+#include "./constants.h"
+#include "./ul_listbase.h"
+#include "./can_sysless.h"
+#include "./can_queue.h"
+#include "./errno.h"
+
+#ifdef CAN_DEBUG
+       #define DEBUGMSG(fmt,args...) can_printk(KERN_ERR "USBCAN(debug): " fmt,\
+       ##args)
+#else
+       #define DEBUGMSG(fmt,args...)
+#endif
+
+#define CANMSG(fmt,args...) can_printk(KERN_ERR "USBCAN: " fmt,##args)
+
+
+extern can_spinlock_t canuser_manipulation_lock;
+
+/**
+ * struct canhardware_t - structure representing pointers to all CAN boards
+ * @nr_boards: number of present boards
+ * @rtr_queue: RTR - remote transmission request queue (expect some changes there)
+ * @rtr_lock: locking for RTR queue
+ * @candevice: array of pointers to CAN devices/boards
+ */
+struct canhardware_t {
+       int nr_boards;
+       struct rtr_id *rtr_queue;
+       can_spinlock_t rtr_lock;
+       struct candevice_t *candevice[MAX_HW_CARDS];
+};
+
+/**
+ * struct candevice_t - CAN device/board structure
+ * @hwname: text string with board type
+ * @candev_idx: board index in canhardware_t.candevice[]
+ * @io_addr: IO/physical MEM address
+ * @res_addr: optional reset register port
+ * @dev_base_addr: CPU translated IO/virtual MEM address
+ * @flags: board flags: %PROGRAMMABLE_IRQ .. interrupt number
+ *     can be programmed into board
+ * @nr_all_chips: number of chips present on the board
+ * @nr_82527_chips: number of Intel 8257 chips
+ * @nr_sja1000_chips: number of Philips SJA100 chips
+ * @chip: array of pointers to the chip structures
+ * @hwspecops: pointer to board specific operations
+ * @hosthardware_p: pointer to the root hardware structure
+ * @sysdevptr: union reserved for pointer to bus specific
+ *     device structure (case @pcidev is used for PCI devices)
+ *
+ * The structure represent configuration and state of associated board.
+ * The driver infrastructure prepares this structure and calls
+ * board type specific board_register() function. The board support provided
+ * register function fills right function pointers in @hwspecops structure.
+ * Then driver setup calls functions init_hw_data(), init_chip_data(),
+ * init_chip_data(), init_obj_data() and program_irq(). Function init_hw_data()
+ * and init_chip_data() have to specify number and types of connected chips
+ * or objects respectively.
+ * The use of @nr_all_chips is preferred over use of fields @nr_82527_chips
+ * and @nr_sja1000_chips in the board non-specific functions.
+ * The @io_addr and @dev_base_addr is filled from module parameters
+ * to the same value. The request_io function can fix-up @dev_base_addr
+ * field if virtual address is different than bus address.
+ */
+struct candevice_t {
+       char *hwname;                   /* text board type */
+       int candev_idx;                 /* board index in canhardware_t.candevice[] */
+       unsigned long io_addr;          /* IO/physical MEM address */
+       unsigned long res_addr;         /* optional reset register port */
+       unsigned long dev_base_addr;    /* CPU translated IO/virtual MEM address */
+       unsigned int flags;
+       int nr_all_chips;
+       int nr_82527_chips;
+       int nr_sja1000_chips;
+       can_spinlock_t device_lock;
+       struct canchip_t *chip[MAX_HW_CHIPS];
+
+       struct hwspecops_t *hwspecops;
+
+       struct canhardware_t *hosthardware_p;
+
+       union {
+               void *anydev;
+           #ifdef CAN_ENABLE_PCI_SUPPORT
+               struct pci_dev *pcidev;
+           #endif /*CAN_ENABLE_PCI_SUPPORT*/
+       } sysdevptr;
+
+};
+
+/**
+ * struct canchip_t - CAN chip state and type information
+ * @chip_type: text string describing chip type
+ * @chip_idx: index of the chip in candevice_t.chip[] array
+ * @chip_irq: chip interrupt number if any
+ * @chip_base_addr: chip base address in the CPU IO or virtual memory space
+ * @flags: chip flags: %CHIP_CONFIGURED .. chip is configured,
+ *     %CHIP_SEGMENTED .. access to the chip is segmented (mainly for i82527 chips)
+ * @clock: chip base clock frequency in Hz
+ * @baudrate: selected chip baudrate in Hz
+ * @write_register: write chip register function copy
+ * @read_register: read chip register function copy
+ * @chip_data: pointer for optional chip specific data extension
+ * @sja_cdr_reg: SJA specific register -
+ *     holds hardware specific options for the Clock Divider
+ *     register. Options defined in the sja1000.h file:
+ *     %CDR_CLKOUT_MASK, %CDR_CLK_OFF, %CDR_RXINPEN, %CDR_CBP, %CDR_PELICAN
+ * @sja_ocr_reg: SJA specific register -
+ *     hold hardware specific options for the Output Control
+ *     register. Options defined in the sja1000.h file:
+ *     %OCR_MODE_BIPHASE, %OCR_MODE_TEST, %OCR_MODE_NORMAL, %OCR_MODE_CLOCK,
+ *     %OCR_TX0_LH, %OCR_TX1_ZZ.
+ * @int_cpu_reg: Intel specific register -
+ *     holds hardware specific options for the CPU Interface
+ *     register. Options defined in the i82527.h file:
+ *     %iCPU_CEN, %iCPU_MUX, %iCPU_SLP, %iCPU_PWD, %iCPU_DMC, %iCPU_DSC, %iCPU_RST.
+ * @int_clk_reg: Intel specific register -
+ *     holds hardware specific options for the Clock Out
+ *     register. Options defined in the i82527.h file:
+ *     %iCLK_CD0, %iCLK_CD1, %iCLK_CD2, %iCLK_CD3, %iCLK_SL0, %iCLK_SL1.
+ * @int_bus_reg: Intel specific register -
+ *     holds hardware specific options for the Bus Configuration
+ *     register. Options defined in the i82527.h file:
+ *     %iBUS_DR0, %iBUS_DR1, %iBUS_DT1, %iBUS_POL, %iBUS_CBY.
+ * @msgobj: array of pointers to individual communication objects
+ * @chipspecops: pointer to the set of chip specific object filled by init_chip_data() function
+ * @hostdevice: pointer to chip hosting board
+ * @max_objects: maximal number of communication objects connected to this chip
+ * @chip_lock: reserved for synchronization of the chip supporting routines
+ *     (not used in the current driver version)
+ * @worker_thread: chip worker thread ID (RT-Linux specific field)
+ * @pend_flags: holds information about pending interrupt and tx_wake() operations
+ *     (RT-Linux specific field). Masks values:
+ *     %MSGOBJ_TX_REQUEST .. some of the message objects requires tx_wake() call,
+ *     %MSGOBJ_IRQ_REQUEST .. chip interrupt processing required
+ *     %MSGOBJ_WORKER_WAKE .. marks, that worker thread should be waked
+ *             for some of above reasons
+ *
+ * The fields @write_register and @read_register are copied from
+ * corresponding fields from @hwspecops structure
+ * (chip->hostdevice->hwspecops->write_register and
+ * chip->hostdevice->hwspecops->read_register)
+ * to speedup can_write_reg() and can_read_reg() functions.
+ */
+struct canchip_t {
+       char *chip_type;
+       int chip_idx;   /* chip index in candevice_t.chip[] */
+       int chip_irq;
+       unsigned long chip_base_addr;
+       unsigned int flags;
+       long clock; /* Chip clock in Hz */
+       long baudrate;
+
+       void (*write_register)(unsigned data,unsigned long address);
+       unsigned (*read_register)(unsigned long address);
+
+       void *chip_data;
+
+       unsigned short sja_cdr_reg; /* sja1000 only! */
+       unsigned short sja_ocr_reg; /* sja1000 only! */
+       unsigned short int_cpu_reg; /* intel 82527 only! */
+       unsigned short int_clk_reg; /* intel 82527 only! */
+       unsigned short int_bus_reg; /* intel 82527 only! */
+
+       struct msgobj_t *msgobj[MAX_MSGOBJS];
+
+       struct chipspecops_t *chipspecops;
+
+       struct candevice_t *hostdevice;
+
+       int max_objects;        /* 1 for sja1000, 15 for i82527 */
+
+       can_spinlock_t chip_lock;
+
+    #ifdef CAN_WITH_RTL
+       pthread_t worker_thread;
+       unsigned long pend_flags;
+    #endif /*CAN_WITH_RTL*/
+};
+
+/**
+ * struct msgobj_t - structure holding communication object state
+ * @obj_base_addr:
+ * @minor: associated device minor number
+ * @object: object number in canchip_t structure +1
+ * @flags: message object flags
+ * @ret: field holding status of the last Tx operation
+ * @qends: pointer to message object corresponding ends structure
+ * @tx_qedge: edge corresponding to transmitted message
+ * @tx_slot: slot holding transmitted message, slot is taken from
+ *     canque_test_outslot() call and is freed by canque_free_outslot()
+ *     or rescheduled canque_again_outslot()
+ * @tx_retry_cnt: transmission attempt counter
+ * @tx_timeout: can be used by chip driver to check for the transmission timeout
+ * @rx_msg: temporary storage to hold received messages before
+ *     calling to canque_filter_msg2edges()
+ * @hostchip: pointer to the &canchip_t structure this object belongs to
+ * @obj_used: counter of users (associated file structures for Linux
+ *     userspace clients) of this object
+ * @obj_users: list of user structures of type &canuser_t.
+ * @obj_flags: message object specific flags. Masks values:
+ *     %MSGOBJ_TX_REQUEST .. the message object requests TX activation
+ *     %MSGOBJ_TX_LOCK .. some IRQ routine or callback on some CPU
+ *             is running inside TX activation processing code
+ * @rx_preconfig_id: place to store RX message identifier for some chip types
+ *              that reuse same object for TX
+ */
+struct msgobj_t {
+       unsigned long obj_base_addr;
+       unsigned int minor;     /* associated device minor number  */
+       unsigned int object;    /* object number in canchip_t +1 for debug printk */
+       unsigned long obj_flags;
+       int ret;
+
+       struct canque_ends_t *qends;
+
+       struct canque_edge_t *tx_qedge;
+       struct canque_slot_t *tx_slot;
+       int tx_retry_cnt;
+       struct timer_list tx_timeout;
+
+       struct canmsg_t rx_msg;
+
+       struct canchip_t *hostchip;
+
+       unsigned long rx_preconfig_id;
+
+       atomic_t obj_used;
+       struct list_head obj_users;
+};
+
+#define CAN_USER_MAGIC 0x05402033
+
+/**
+ * struct canuser_t - structure holding CAN user/client state
+ * @flags: used to distinguish Linux/RT-Linux type
+ * @peers: for connection into list of object users
+ * @qends: pointer to the ends structure corresponding for this user
+ * @msgobj: communication object the user is connected to
+ * @rx_edge0: default receive queue for filter IOCTL
+ * @userinfo: stores user context specific information.
+ *     The field @fileinfo.file holds pointer to open device file state structure
+ *     for the Linux user-space client applications
+ * @magic: magic number to check consistency when pointer is retrieved
+ *     from file private field
+ */
+struct canuser_t {
+       unsigned long flags;
+       struct list_head peers;
+       struct canque_ends_t *qends;
+       struct msgobj_t *msgobj;
+       struct canque_edge_t *rx_edge0; /* simplifies IOCTL */
+        union {
+               struct {
+                       struct file *file;  /* back ptr to file */
+               } fileinfo;
+           #ifdef CAN_WITH_RTL
+               struct {
+                       struct rtl_file *file;
+               } rtlinfo;
+           #endif /*CAN_WITH_RTL*/
+       } userinfo;
+       int magic;
+};
+
+/**
+ * struct hwspecops_t - hardware/board specific operations
+ * @request_io: reserve io or memory range for can board
+ * @release_io: free reserved io memory range
+ * @reset: hardware reset routine
+ * @init_hw_data: called to initialize &candevice_t structure, mainly
+ *     @res_add, @nr_all_chips, @nr_82527_chips, @nr_sja1000_chips
+ *     and @flags fields
+ * @init_chip_data: called initialize each &canchip_t structure, mainly
+ *     @chip_type, @chip_base_addr, @clock and chip specific registers.
+ *     It is responsible to setup &canchip_t->@chipspecops functions
+ *     for non-standard chip types (type other than "i82527", "sja1000" or "sja1000p")
+ * @init_obj_data: called initialize each &msgobj_t structure,
+ *     mainly @obj_base_addr field.
+ * @program_irq: program interrupt generation hardware of the board
+ *     if flag %PROGRAMMABLE_IRQ is present for specified device/board
+ * @write_register: low level write register routine
+ * @read_register: low level read register routine
+ */
+struct hwspecops_t {
+       int (*request_io)(struct candevice_t *candev);
+       int (*release_io)(struct candevice_t *candev);
+       int (*reset)(struct candevice_t *candev);
+       int (*init_hw_data)(struct candevice_t *candev);
+       int (*init_chip_data)(struct candevice_t *candev, int chipnr);
+       int (*init_obj_data)(struct canchip_t *chip, int objnr);
+       int (*program_irq)(struct candevice_t *candev);
+       void (*write_register)(unsigned data,unsigned long address);
+       unsigned (*read_register)(unsigned long address);
+};
+
+/**
+ * struct chipspecops_t - can controller chip specific operations
+ * @chip_config: CAN chip configuration
+ * @baud_rate: set communication parameters
+ * @standard_mask: setup of mask for message filtering
+ * @extended_mask: setup of extended mask for message filtering
+ * @message15_mask: set mask of i82527 message object 15
+ * @clear_objects: clears state of all message object residing in chip
+ * @config_irqs: tunes chip hardware interrupt delivery
+ * @pre_read_config: prepares message object for message reception
+ * @pre_write_config: prepares message object for message transmission
+ * @send_msg: initiate message transmission
+ * @remote_request: configures message object and asks for RTR message
+ * @check_tx_stat: checks state of transmission engine
+ * @wakeup_tx: wakeup TX processing
+ * @filtch_rq: optional routine for propagation of outgoing edges filters to HW
+ * @enable_configuration: enable chip configuration mode
+ * @disable_configuration: disable chip configuration mode
+ * @set_btregs: configures bitrate registers
+ * @attach_to_chip: attaches to the chip, setups registers and possibly state informations
+ * @release_chip: called before chip structure removal if %CHIP_ATTACHED is set
+ * @start_chip: starts chip message processing
+ * @stop_chip: stops chip message processing
+ * @irq_handler: interrupt service routine
+ * @irq_accept: optional fast irq accept routine responsible for blocking further interrupts
+ */
+struct chipspecops_t {
+       int (*chip_config)(struct canchip_t *chip);
+       int (*baud_rate)(struct canchip_t *chip, int rate, int clock, int sjw,
+                                               int sampl_pt, int flags);
+       int (*standard_mask)(struct canchip_t *chip, unsigned short code,
+                                                       unsigned short mask);
+       int (*extended_mask)(struct canchip_t *chip, unsigned long code,
+                                                       unsigned long mask);
+       int (*message15_mask)(struct canchip_t *chip, unsigned long code,
+                                                       unsigned long mask);
+       int (*clear_objects)(struct canchip_t *chip);
+       int (*config_irqs)(struct canchip_t *chip, short irqs);
+       int (*pre_read_config)(struct canchip_t *chip, struct msgobj_t *obj);
+       int (*pre_write_config)(struct canchip_t *chip, struct msgobj_t *obj,
+                                                       struct canmsg_t *msg);
+       int (*send_msg)(struct canchip_t *chip, struct msgobj_t *obj,
+                                                       struct canmsg_t *msg);
+       int (*remote_request)(struct canchip_t *chip, struct msgobj_t *obj);
+       int (*check_tx_stat)(struct canchip_t *chip);
+       int (*wakeup_tx)(struct canchip_t *chip, struct msgobj_t *obj);
+       int (*filtch_rq)(struct canchip_t *chip, struct msgobj_t *obj);
+       int (*enable_configuration)(struct canchip_t *chip);
+       int (*disable_configuration)(struct canchip_t *chip);
+       int (*set_btregs)(struct canchip_t *chip, unsigned short btr0,
+                                                       unsigned short btr1);
+       int (*attach_to_chip)(struct canchip_t *chip);
+       int (*release_chip)(struct canchip_t *chip);
+       int (*start_chip)(struct canchip_t *chip);
+       int (*stop_chip)(struct canchip_t *chip);
+       int (*irq_handler)(int irq, struct canchip_t *chip);
+       int (*irq_accept)(int irq, struct canchip_t *chip);
+};
+
+struct mem_addr {
+       void *address;
+       struct mem_addr *next;
+       size_t size;
+};
+
+/* Structure for the RTR queue */
+struct rtr_id {
+       unsigned long id;
+       struct canmsg_t *rtr_message;
+       wait_queue_head_t rtr_wq;
+       struct rtr_id *next;
+};
+
+extern int major;
+extern int minor[MAX_TOT_CHIPS];
+extern int extended;
+extern int baudrate[MAX_TOT_CHIPS];
+extern char *hw[MAX_HW_CARDS];
+extern int irq[MAX_IRQ];
+extern unsigned long io[MAX_HW_CARDS];
+extern int processlocal;
+
+extern struct canhardware_t *hardware_p;
+//extern struct canchip_t *chips_p[MAX_TOT_CHIPS];
+struct canchip_t *chips_p[MAX_TOT_CHIPS];
+extern struct msgobj_t *objects_p[MAX_TOT_MSGOBJS];
+
+extern struct mem_addr *mem_head;
+
+
+#if defined(CONFIG_OC_LINCAN_PORTIO_ONLY)
+extern inline void can_write_reg(const struct canchip_t *chip, unsigned char data, unsigned address)
+{
+       outb(data, chip->chip_base_addr+address);
+}
+extern inline unsigned can_read_reg(const struct canchip_t *chip, unsigned address)
+{
+       return inb(chip->chip_base_addr+address);
+}
+extern inline void canobj_write_reg(const struct canchip_t *chip, const struct msgobj_t *obj,
+                               unsigned char data, unsigned address)
+{
+       outb(data, obj->obj_base_addr+address);
+}
+extern inline unsigned canobj_read_reg(const struct canchip_t *chip, const struct msgobj_t *obj,
+                               unsigned address)
+{
+       return inb(obj->obj_base_addr+address);
+}
+
+#elif defined(CONFIG_OC_LINCAN_MEMIO_ONLY)
+extern inline void can_write_reg(const struct canchip_t *chip, unsigned char data, unsigned address)
+{
+       writeb(data, chip->chip_base_addr+address);
+}
+extern inline unsigned can_read_reg(const struct canchip_t *chip, unsigned address)
+{
+       return readb(chip->chip_base_addr+address);
+}
+extern inline void canobj_write_reg(const struct canchip_t *chip, const struct msgobj_t *obj,
+                               unsigned char data, unsigned address)
+{
+       writeb(data, obj->obj_base_addr+address);
+}
+extern inline unsigned canobj_read_reg(const struct canchip_t *chip, const struct msgobj_t *obj,
+                               unsigned address)
+{
+       return readb(obj->obj_base_addr+address);
+}
+
+#else /*CONFIG_OC_LINCAN_DYNAMICIO*/
+#ifndef CONFIG_OC_LINCAN_DYNAMICIO
+#define CONFIG_OC_LINCAN_DYNAMICIO
+#endif
+
+/* Inline function to write to the hardware registers. The argument address is
+ * relative to the memory map of the chip and not the absolute memory address.
+ */
+extern inline void can_write_reg(const struct canchip_t *chip, unsigned char data, unsigned address)
+{
+       unsigned long address_to_write;
+       address_to_write = chip->chip_base_addr+address;
+       chip->write_register(data, address_to_write);
+}
+
+extern inline unsigned can_read_reg(const struct canchip_t *chip, unsigned address)
+{
+       unsigned long address_to_read;
+       address_to_read = chip->chip_base_addr+address;
+       return chip->read_register(address_to_read);
+}
+
+extern inline void canobj_write_reg(const struct canchip_t *chip, const struct msgobj_t *obj,
+                               unsigned char data, unsigned address)
+{
+       unsigned long address_to_write;
+       address_to_write = obj->obj_base_addr+address;
+       chip->write_register(data, address_to_write);
+}
+
+extern inline unsigned canobj_read_reg(const struct canchip_t *chip, const struct msgobj_t *obj,
+                               unsigned address)
+{
+       unsigned long address_to_read;
+       address_to_read = obj->obj_base_addr+address;
+       return chip->read_register(address_to_read);
+}
+
+#endif /*CONFIG_OC_LINCAN_DYNAMICIO*/
+
+int can_base_addr_fixup(struct candevice_t *candev, unsigned long new_base);
+int can_request_io_region(unsigned long start, unsigned long n, const char *name);
+void can_release_io_region(unsigned long start, unsigned long n);
+int can_request_mem_region(unsigned long start, unsigned long n, const char *name);
+void can_release_mem_region(unsigned long start, unsigned long n);
+
+struct boardtype_t {
+       const char *boardtype;
+       int (*board_register)(struct hwspecops_t *hwspecops);
+       int irqnum;
+};
+
+const struct boardtype_t* boardtype_find(const char *str);
+
+int can_check_dev_taken(void *anydev);
+
+#if defined(can_gettimeofday) && defined(CAN_MSG_VERSION_2) && 1
+static inline
+void can_filltimestamp(canmsg_tstamp_t *ptimestamp)
+{
+       can_gettimeofday(ptimestamp);
+}
+#else /* No timestamp support, set field to zero */
+static inline
+void can_filltimestamp(canmsg_tstamp_t *ptimestamp)
+{
+    #ifdef CAN_MSG_VERSION_2
+       ptimestamp->tv_sec = 0;
+       ptimestamp->tv_usec = 0;
+    #else /* CAN_MSG_VERSION_2 */
+       *ptimestamp = 0;
+    #endif /* CAN_MSG_VERSION_2 */
+
+}
+#endif /* End of timestamp source selection */
+
+#ifdef CAN_WITH_RTL
+extern int can_rtl_priority;
+#endif /*CAN_WITH_RTL*/
+
+#endif /* MAIN_H */
+
diff --git a/embedded/app/usbcan/can/modparms.h b/embedded/app/usbcan/can/modparms.h
new file mode 100644 (file)
index 0000000..6691931
--- /dev/null
@@ -0,0 +1,10 @@
+/* mod_parms.h
+ * Header file for the Linux CAN-bus driver.
+ * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
+ * Rewritten for new CAN queues by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.3  17 Jun 2004
+ */
+
+int parse_mod_parms(void);
diff --git a/embedded/app/usbcan/can/setup.h b/embedded/app/usbcan/can/setup.h
new file mode 100644 (file)
index 0000000..d35a8b1
--- /dev/null
@@ -0,0 +1,16 @@
+/* setup.h
+ * Header file for the Linux CAN-bus driver.
+ * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
+ * Rewritten for new CAN queues by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.3  17 Jun 2004
+ */
+
+int init_hw_struct(void);
+int list_hw(void);
+void *can_checked_malloc(size_t size);
+int can_checked_free(void *address_p);
+int can_del_mem_list(void);
+int can_chip_setup_irq(struct canchip_t *chip);
+void can_chip_free_irq(struct canchip_t *chip);
diff --git a/embedded/app/usbcan/can/sja1000p.h b/embedded/app/usbcan/can/sja1000p.h
new file mode 100644 (file)
index 0000000..fe81a9c
--- /dev/null
@@ -0,0 +1,205 @@
+/* sja1000p.h
+ * Header file for the Linux CAN-bus driver.
+ * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
+ * Added by T.Motylewski@bfad.de
+ * See app. note an97076.pdf from Philips Semiconductors
+ * and SJA1000 data sheet
+ * PELICAN mode
+ * This software is released under the GPL-License.
+ * Version lincan-0.3  17 Jun 2004
+ */
+
+#ifndef SJA1000P_H
+#define SJA1000P_H
+
+int sja1000p_chip_config(struct canchip_t *chip);
+int sja1000p_extended_mask(struct canchip_t *chip, unsigned long code, unsigned long mask);
+int sja1000p_baud_rate(struct canchip_t *chip, int rate, int clock, int sjw,
+               int sampl_pt, int flags);
+int sja1000p_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj);
+int sja1000p_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj,
+               struct canmsg_t *msg);
+int sja1000p_send_msg(struct canchip_t *chip, struct msgobj_t *obj,
+               struct canmsg_t *msg);
+int sja1000p_fill_chipspecops(struct canchip_t *chip);
+int sja1000p_irq_handler(int irq, struct canchip_t *chip);
+
+
+/* PeliCAN mode */
+enum SJA1000_PeliCAN_regs {
+       SJAMOD  = 0x00,
+/// Command register
+       SJACMR  = 0x01,
+/// Status register
+       SJASR   = 0x02,
+/// Interrupt register
+       SJAIR   = 0x03,
+/// Interrupt Enable
+       SJAIER  = 0x04,
+/// Bus Timing register 0
+       SJABTR0 = 0x06,
+/// Bus Timing register 1
+       SJABTR1 = 0x07,
+/// Output Control register
+       SJAOCR  = 0x08,
+/// Arbitration Lost Capture
+       SJAALC  = 0x0b,
+/// Error Code Capture
+       SJAECC  = 0x0c,
+/// Error Warning Limit
+       SJAEWLR = 0x0d,
+/// RX Error Counter
+       SJARXERR = 0x0e,
+/// TX Error Counter
+       SJATXERR0 = 0x0e,
+       SJATXERR1 = 0x0f,
+/// Rx Message Counter (number of msgs. in RX FIFO
+       SJARMC  = 0x1d,
+/// Rx Buffer Start Addr. (address of current MSG)
+       SJARBSA = 0x1e,
+/// Transmit Buffer (write) Receive Buffer (read) Frame Information
+       SJAFRM = 0x10,
+/// ID bytes (11 bits in 0 and 1 or 16 bits in 0,1 and 13 bits in 2,3 (extended))
+       SJAID0 = 0x11, SJAID1 = 0x12,
+/// ID cont. for extended frames
+       SJAID2 = 0x13, SJAID3 = 0x14,
+/// Data start standard frame
+       SJADATS = 0x13,
+/// Data start extended frame
+       SJADATE = 0x15,
+/// Acceptance Code (4 bytes) in RESET mode
+       SJAACR0 = 0x10,
+/// Acceptance Mask (4 bytes) in RESET mode
+       SJAAMR0 = 0x14,
+/// 4 bytes
+       SJA_PeliCAN_AC_LEN = 4,
+/// Clock Divider
+       SJACDR = 0x1f
+};
+
+/** Mode Register 0x00 */
+enum sja1000_PeliCAN_MOD {
+       sjaMOD_SM = 1<<4,  // Sleep Mode (writable only in OPERATING mode)
+       sjaMOD_AFM= 1<<3,  // Acceptance Filter Mode (writable only in RESET)
+       sjaMOD_STM= 1<<2,  // Self Test Mode (writable only in RESET)
+       sjaMOD_LOM= 1<<1,  // Listen Only Mode (writable only in RESET)
+       sjaMOD_RM = 1      // Reset Mode
+};
+
+/** Command Register 0x01 */
+enum sja1000_PeliCAN_CMR {
+       sjaCMR_SRR= 1<<4,  // Self Reception Request (GoToSleep in BASIC mode)
+       sjaCMR_CDO= 1<<3,  // Clear Data Overrun
+       sjaCMR_RRB= 1<<2,  // Release Receive Buffer
+       sjaCMR_AT = 1<<1,  // Abort Transmission
+       sjaCMR_TR = 1 };   // Transmission Request
+
+/** Status Register 0x02 */
+enum sja1000_SR {
+       sjaSR_BS  = 1<<7,  // Bus Status
+       sjaSR_ES  = 1<<6,  // Error Status
+       sjaSR_TS  = 1<<5,  // Transmit Status
+       sjaSR_RS  = 1<<4,  // Receive Status
+       sjaSR_TCS = 1<<3,  // Transmission Complete Status
+       sjaSR_TBS = 1<<2,  // Transmit Buffer Status
+       sjaSR_DOS = 1<<1,  // Data Overrun Status
+       sjaSR_RBS = 1 };   // Receive Buffer Status
+
+/** Interrupt Enable Register 0x04 */
+enum sja1000_PeliCAN_IER {
+       sjaIER_BEIE= 1<<7, // Bus Error Interrupt Enable
+       sjaIER_ALIE= 1<<6, // Arbitration Lost Interrupt Enable
+       sjaIER_EPIE= 1<<5, // Error Passive Interrupt Enable
+       sjaIER_WUIE= 1<<4, // Wake-Up Interrupt Enable
+       sjaIER_DOIE= 1<<3, // Data Overrun Interrupt Enable
+       sjaIER_EIE = 1<<2, // Error Warning Interrupt Enable
+       sjaIER_TIE = 1<<1, // Transmit Interrupt Enable
+       sjaIER_RIE = 1,    // Receive Interrupt Enable
+       sjaENABLE_INTERRUPTS = sjaIER_BEIE|sjaIER_EPIE|sjaIER_DOIE|sjaIER_EIE|sjaIER_TIE|sjaIER_RIE,
+       sjaDISABLE_INTERRUPTS = 0
+// WARNING: the chip automatically enters RESET (bus off) mode when
+       // error counter > 255
+};
+
+/** Arbitration Lost Capture Register 0x0b.
+ * Counting starts from 0 (bit1 of ID). Bits 5-7 reserved*/
+enum sja1000_PeliCAN_ALC {
+       sjaALC_SRTR = 0x0b,// Arbitration lost in bit SRTR
+       sjaALC_IDE  = 0x1c, // Arbitration lost in bit IDE
+       sjaALC_RTR  = 0x1f, // Arbitration lost in RTR
+};
+
+/** Error Code Capture Register 0x0c*/
+enum sja1000_PeliCAN_ECC {
+       sjaECC_ERCC1 = 1<<7,
+       sjaECC_ERCC0 = 1<<6,
+       sjaECC_BIT   = 0,
+       sjaECC_FORM  = sjaECC_ERCC0,
+       sjaECC_STUFF = sjaECC_ERCC1,
+       sjaECC_OTHER = sjaECC_ERCC0 | sjaECC_ERCC1,
+       sjaECC_DIR   = 1<<5,    // 1 == RX, 0 == TX
+       sjaECC_SEG_M = (1<<5) -1 // Segment mask, see page 37 of SJA1000 Data Sheet
+};
+
+/** Frame format information 0x10 */
+enum sja1000_PeliCAN_FRM {
+       sjaFRM_FF = 1<<7, // Frame Format 1 == extended, 0 == standard
+       sjaFRM_RTR = 1<<6, // Remote request
+       sjaFRM_DLC_M = (1<<4)-1 // Length Mask
+};
+
+
+/** Interrupt (status) Register 0x03 */
+enum sja1000_PeliCAN_IR {
+       sjaIR_BEI = 1<<7,  // Bus Error Interrupt
+       sjaIR_ALI = 1<<6,  // Arbitration Lost Interrupt
+       sjaIR_EPI = 1<<5,  // Error Passive Interrupt (entered error passive state or error active state)
+       sjaIR_WUI = 1<<4,  // Wake-Up Interrupt
+       sjaIR_DOI = 1<<3,  // Data Overrun Interrupt
+       sjaIR_EI  = 1<<2,  // Error Interrupt
+       sjaIR_TI  = 1<<1,  // Transmit Interrupt
+       sjaIR_RI  = 1      // Receive Interrupt
+};
+
+/** Bus Timing 1 Register 0x07 */
+enum sja1000_BTR1 {
+       sjaMAX_TSEG1 = 15,
+       sjaMAX_TSEG2 = 7
+};
+
+/** Output Control Register 0x08 */
+enum sja1000_OCR {
+       sjaOCR_MODE_BIPHASE = 0,
+       sjaOCR_MODE_TEST = 1,
+       sjaOCR_MODE_NORMAL = 2,
+       sjaOCR_MODE_CLOCK = 3,
+/// TX0 push-pull not inverted
+       sjaOCR_TX0_LH = 0x18,
+/// TX1 floating (off)
+       sjaOCR_TX1_ZZ = 0
+};
+
+/** Clock Divider register 0x1f */
+enum sja1000_CDR {
+       sjaCDR_PELICAN = 1<<7,
+/// bypass input comparator
+       sjaCDR_CBP = 1<<6,
+/// switch TX1 to generate RX INT
+       sjaCDR_RXINPEN = 1<<5,
+       sjaCDR_CLK_OFF = 1<<3,
+/// f_out = f_osc/(2*(CDR[2:0]+1)) or f_osc if CDR[2:0]==7
+       sjaCDR_CLKOUT_DIV1 = 7,
+       sjaCDR_CLKOUT_DIV2 = 0,
+       sjaCDR_CLKOUT_DIV4 = 1,
+       sjaCDR_CLKOUT_DIV6 = 2,
+       sjaCDR_CLKOUT_DIV8 = 3,
+       sjaCDR_CLKOUT_DIV10 = 4,
+       sjaCDR_CLKOUT_DIV12 = 5,
+       sjaCDR_CLKOUT_DIV14 = 6,
+       sjaCDR_CLKOUT_MASK = 7
+};
+
+/** flags for sja1000_baud_rate */
+#define BTR1_SAM (1<<1)
+
+#endif /* SJA1000P_H */
diff --git a/embedded/app/usbcan/can/ul_listbase.h b/embedded/app/usbcan/can/ul_listbase.h
new file mode 100644 (file)
index 0000000..2d4fece
--- /dev/null
@@ -0,0 +1,287 @@
+#ifndef _UL_LISTBASE_H
+#define _UL_LISTBASE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef __KERNEL__
+
+#define LIST_POISON1  ((void *) 0)
+#define LIST_POISON2  ((void *) 0)
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+       struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+       struct list_head name = LIST_HEAD_INIT(name)
+
+#define INIT_LIST_HEAD(ptr) do { \
+       (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries. 
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *new,
+                             struct list_head *prev,
+                             struct list_head *next)
+{
+       next->prev = new;
+       new->next = next;
+       new->prev = prev;
+       prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+       __list_add(new, head, head->next);
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+       __list_add(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head * prev, struct list_head * next)
+{
+       next->prev = prev;
+       prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+static inline void list_del(struct list_head *entry)
+{
+       __list_del(entry->prev, entry->next);
+       entry->next = LIST_POISON1;
+       entry->prev = LIST_POISON2;
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+       __list_del(entry->prev, entry->next);
+       INIT_LIST_HEAD(entry); 
+}
+
+/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+        __list_del(list->prev, list->next);
+        list_add(list, head);
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+                                 struct list_head *head)
+{
+        __list_del(list->prev, list->next);
+        list_add_tail(list, head);
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(struct list_head *head)
+{
+       return head->next == head;
+}
+
+static inline void __list_splice(struct list_head *list,
+                                struct list_head *head)
+{
+       struct list_head *first = list->next;
+       struct list_head *last = list->prev;
+       struct list_head *where = head->next;
+
+       first->prev = head;
+       head->next = first;
+
+       last->next = where;
+       where->prev = last;
+}
+
+/**
+ * list_splice - join two lists
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice(struct list_head *list, struct list_head *head)
+{
+       if (!list_empty(list))
+               __list_splice(list, head);
+}
+
+/**
+ * list_splice_init - join two lists and reinitialise the emptied list.
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_init(struct list_head *list,
+                                   struct list_head *head)
+{
+       if (!list_empty(list)) {
+               __list_splice(list, head);
+               INIT_LIST_HEAD(list);
+       }
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr:       the &struct list_head pointer.
+ * @type:      the type of the struct this is embedded in.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+       container_of(ptr, type, member)
+
+/**
+ * list_for_each       -       iterate over a list
+ * @pos:       the &struct list_head to use as a loop counter.
+ * @head:      the head for your list.
+ */
+#define list_for_each(pos, head) \
+       for (pos = (head)->next, prefetch(pos->next); pos != (head); \
+               pos = pos->next, prefetch(pos->next))
+
+/**
+ * __list_for_each     -       iterate over a list
+ * @pos:       the &struct list_head to use as a loop counter.
+ * @head:      the head for your list.
+ *
+ * This variant differs from list_for_each() in that it's the
+ * simplest possible list iteration code, no prefetching is done.
+ * Use this for code that knows the list to be very short (empty
+ * or 1 entry) most of the time.
+ */
+#define __list_for_each(pos, head) \
+       for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * list_for_each_prev  -       iterate over a list backwards
+ * @pos:       the &struct list_head to use as a loop counter.
+ * @head:      the head for your list.
+ */
+#define list_for_each_prev(pos, head) \
+       for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
+               pos = pos->prev, prefetch(pos->prev))
+               
+/**
+ * list_for_each_safe  -       iterate over a list safe against removal of list entry
+ * @pos:       the &struct list_head to use as a loop counter.
+ * @n:         another &struct list_head to use as temporary storage
+ * @head:      the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+       for (pos = (head)->next, n = pos->next; pos != (head); \
+               pos = n, n = pos->next)
+
+/**
+ * list_for_each_entry -       iterate over list of given type
+ * @pos:       the type * to use as a loop counter.
+ * @head:      the head for your list.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member)                         \
+       for (pos = list_entry((head)->next, typeof(*pos), member),      \
+                    prefetch(pos->member.next);                        \
+            &pos->member != (head);                                    \
+            pos = list_entry(pos->member.next, typeof(*pos), member),  \
+                    prefetch(pos->member.next))
+
+/**
+ * list_for_each_entry_reverse - iterate backwards over list of given type.
+ * @pos:       the type * to use as a loop counter.
+ * @head:      the head for your list.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_reverse(pos, head, member)                 \
+       for (pos = list_entry((head)->prev, typeof(*pos), member),      \
+                    prefetch(pos->member.prev);                        \
+            &pos->member != (head);                                    \
+            pos = list_entry(pos->member.prev, typeof(*pos), member),  \
+                    prefetch(pos->member.prev))
+
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos:       the type * to use as a loop counter.
+ * @n:         another type * to use as temporary storage
+ * @head:      the head for your list.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member)                 \
+       for (pos = list_entry((head)->next, typeof(*pos), member),      \
+               n = list_entry(pos->member.next, typeof(*pos), member); \
+            &pos->member != (head);                                    \
+            pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+#else /*__KERNEL__*/
+
+#include <linux/list.h>
+
+#endif /*__KERNEL__*/
+
+#ifdef __cplusplus
+} /* extern "C"*/
+#endif
+
+#endif /* _UL_LISTBASE_H */
diff --git a/embedded/app/usbcan/can/ul_usb1.h b/embedded/app/usbcan/can/ul_usb1.h
new file mode 100644 (file)
index 0000000..385f4e3
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef UL_USB1_H
+#define UL_USB1_H
+
+/* ul_usb1.h
+ * Header file for the Linux CAN-bus driver.
+ * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
+ * Rewritten for new CAN queues by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.3  17 Jun 2004
+ */
+
+struct ul_usb1_chip_data
+{
+       int flags;
+};
+
+#define UL_USB1_CHIP_MASK_SET (1<<0)
+#define UL_USB1_CHIP_BAUD_SET (1<<1)
+
+int ul_usb1_init(void);
+void ul_usb1_exit(void);
+
+extern int ul_usb1_register(struct hwspecops_t *hwspecops);
+
+#endif /* UL_USB1_H */
diff --git a/embedded/app/usbcan/can_quesysless.c b/embedded/app/usbcan/can_quesysless.c
new file mode 100644 (file)
index 0000000..f11f90d
--- /dev/null
@@ -0,0 +1,518 @@
+/* can_quesysless.c - CAN message queues functions for the Linux kernel
+ * Linux CAN-bus device driver.
+ * New CAN queues by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.3  17 Jun 2004
+ */
+
+#include "./can/can.h"
+#include "./can/can_sysdep.h"
+#include "./can/can_queue.h"
+
+// #define CAN_DEBUG
+
+extern atomic_t edge_num_cnt;
+
+#ifdef CAN_DEBUG
+       #define DEBUGQUE(fmt,args...) can_printk(KERN_ERR "can_quesysless (debug): " fmt,\
+       ##args)
+
+#else
+       #define DEBUGQUE(fmt,args...)
+#endif
+
+#define ERRMSGQUE(fmt,args...) can_printk(KERN_ERR "can_quesysless: " fmt,\
+       ##args)
+
+
+/*
+ * Modifies Tx message processing
+ *  0 .. local message processing disabled
+ *  1 .. local messages disabled by default but can be enabled by canque_set_filt
+ *  2 .. local messages enabled by default, can be disabled by canque_set_filt
+ */
+extern int processlocal;
+
+void canque_dead_func(unsigned long data);
+
+/* Support for dead ends structures left after client close */
+can_spinlock_t canque_dead_func_lock;
+LIST_HEAD(canque_dead_ends);
+/* retrieved by list_entry(canque_dead_ends.next,struct canque_ends_t,dead_peers) */
+LIST_HEAD(canque_dead_edges);
+/* retrieved by list_entry(canque_dead_edges.next,struct canque_edge_t,inpeers) */
+// DECLARE_TASKLET(canque_dead_tl, canque_dead_func, 0);
+/* activated by tasklet_schedule(&canque_dead_tl) */
+
+
+static inline
+struct canque_edge_t *canque_dead_edges_cut_first(void)
+{
+       can_spin_irqflags_t flags;
+       struct canque_edge_t *edge;
+       can_spin_lock_irqsave(&canque_dead_func_lock, flags);
+       if(list_empty(&canque_dead_edges))
+               edge=NULL;
+       else{
+               edge=list_entry(canque_dead_edges.next,struct canque_edge_t,inpeers);
+               list_del(&edge->inpeers);
+       }
+       can_spin_unlock_irqrestore(&canque_dead_func_lock, flags);
+       return edge;
+}
+
+void canque_dead_func(unsigned long data)
+{
+       can_spin_irqflags_t flags;
+       struct canque_edge_t *qedge;
+       struct canque_ends_t *qends;
+       struct list_head *entry;
+
+       while((qedge=canque_dead_edges_cut_first())){
+               DEBUGQUE("edge %d disposed\n",qedge->edge_num);
+           #ifdef CAN_WITH_RTL
+               if(canque_fifo_test_fl(&qedge->fifo,RTL_MEM)){
+                       canque_dispose_edge_rtl(qedge);
+                       continue;
+               }
+           #endif /*CAN_WITH_RTL*/
+               canque_fifo_done_kern(&qedge->fifo);
+               free(qedge);
+       }
+
+       can_spin_lock_irqsave(&canque_dead_func_lock, flags);
+       entry=canque_dead_ends.next;
+       while(entry!=&canque_dead_ends){
+               qends=list_entry(entry,struct canque_ends_t,dead_peers);
+               entry=entry->next;
+               if(!list_empty(&qends->inlist))
+                       continue;
+               if(!list_empty(&qends->outlist))
+                       continue;
+               can_spin_lock_irqsave(&canque_dead_func_lock, flags);
+               list_del(&qends->dead_peers);
+               can_spin_unlock_irqrestore(&canque_dead_func_lock,flags);
+               DEBUGQUE("ends structure disposed\n");
+           #ifdef CAN_WITH_RTL
+               if(qends->ends_flags&CAN_ENDSF_MEM_RTL){
+                       canque_ends_free_rtl(qends);
+                       continue;
+               }
+           #endif /*CAN_WITH_RTL*/
+               free(qends);
+       }
+       can_spin_unlock_irqrestore(&canque_dead_func_lock,flags);
+}
+
+// static inline void canque_dead_tasklet_schedule(void)
+// {
+//     #ifdef CAN_WITH_RTL
+//     if(!rtl_rt_system_is_idle()){
+//             set_bit(CAN_RTL2LIN_PEND_DEAD_b,&canqueue_rtl2lin_pend);
+//             rtl_global_pend_irq (canqueue_rtl_irq);
+//             return;
+//     }
+//     #endif /*CAN_WITH_RTL*/
+//
+//     tasklet_schedule(&canque_dead_tl);
+// }
+
+
+void canque_edge_do_dead(struct canque_edge_t *edge)
+{
+       can_spin_irqflags_t flags;
+
+       canque_notify_bothends(edge,CANQUEUE_NOTIFY_NOUSR);
+    #ifdef CAN_WITH_RTL
+       /* The problem of the above call is, that in RT-Linux to Linux notify
+          case is edge scheduled for delayed notify delivery, this needs
+          to be reflected there */
+       if(atomic_read(&edge->edge_used)>0){
+               can_spin_lock_irqsave(&edge->inends->ends_lock, flags);
+               can_spin_lock(&edge->outends->ends_lock);
+               if(atomic_read(&edge->edge_used)>0){
+                       /* left edge to live for a while, banshee comes again in a while */
+                       canque_fifo_clear_fl(&edge->fifo,DEAD);
+                       can_spin_unlock(&edge->outends->ends_lock);
+                       can_spin_unlock_irqrestore(&edge->inends->ends_lock, flags);
+                       can_printk(KERN_ERR "can_quertl (debug): canque_edge_do_dead postponed\n");
+                       return;
+               }
+               can_spin_unlock(&edge->outends->ends_lock);
+               can_spin_unlock_irqrestore(&edge->inends->ends_lock, flags);
+       }
+    #endif /*CAN_WITH_RTL*/
+
+       if(canqueue_disconnect_edge(edge)<0){
+               ERRMSGQUE("canque_edge_do_dead: canqueue_disconnect_edge failed !!!\n");
+               return;
+       }
+
+       can_spin_lock_irqsave(&canque_dead_func_lock, flags);
+       list_add(&edge->inpeers,&canque_dead_edges);
+       can_spin_unlock_irqrestore(&canque_dead_func_lock, flags);
+//     canque_dead_tasklet_schedule();
+       canque_dead_func(0);
+}
+
+
+
+/*if(qends->ends_flags & CAN_ENDSF_DEAD){
+       can_spin_lock_irqsave(&canque_dead_func_lock, flags);
+       list_del(&qends->dead_peers);
+       list_add(&qends->dead_peers,&canque_dead_ends);
+       can_spin_unlock_irqrestore(&canque_dead_func_lock, flags);
+       tasklet_schedule(&canque_dead_tl);
+}*/
+
+
+/**
+ * canqueue_notify_kern - notification callback handler for Linux userspace clients
+ * @qends: pointer to the callback side ends structure
+ * @qedge: edge which invoked notification
+ * @what: notification type
+ *
+ * The notification event is handled directly by call of this function except case,
+ * when called from RT-Linux context in mixed mode Linux/RT-Linux compilation.
+ * It is not possible to directly call Linux kernel synchronization primitives
+ * in such case. The notification request is postponed and signaled by @pending_inops flags
+ * by call canqueue_rtl2lin_check_and_pend() function.
+ * The edge reference count is increased until until all pending notifications are processed.
+ */
+void canqueue_notify_kern(struct canque_ends_t *qends, struct canque_edge_t *qedge, int what)
+{
+       DEBUGQUE("canqueue_notify_kern for edge %d, use %d and event %d\n",
+                       qedge->edge_num,(int)atomic_read(&qedge->edge_used),what);
+
+       /* delay event delivery for RT-Linux -> kernel notifications */
+       if(canqueue_rtl2lin_check_and_pend(qends,qedge,what)){
+               DEBUGQUE("canqueue_notify_kern postponed\n");
+               return;
+       }
+
+       switch(what){
+               case CANQUEUE_NOTIFY_EMPTY:
+//                     wake_up(&qends->endinfo.fileinfo.emptyq);
+                       if(canque_fifo_test_and_clear_fl(&qedge->fifo, FREEONEMPTY))
+                               canque_edge_decref(qedge);
+                       break;
+               case CANQUEUE_NOTIFY_SPACE:
+//                     wake_up(&qends->endinfo.fileinfo.writeq);
+                   #ifdef CAN_ENABLE_KERN_FASYNC
+                       /* Asynchronous I/O processing */
+                       kill_fasync(&qends->endinfo.fileinfo.fasync, SIGIO, POLL_OUT);
+                   #endif /*CAN_ENABLE_KERN_FASYNC*/
+                       break;
+               case CANQUEUE_NOTIFY_PROC:
+//                     wake_up(&qends->endinfo.fileinfo.readq);
+                   #ifdef CAN_ENABLE_KERN_FASYNC
+                       /* Asynchronous I/O processing */
+                       kill_fasync(&qends->endinfo.fileinfo.fasync, SIGIO, POLL_IN);
+                   #endif /*CAN_ENABLE_KERN_FASYNC*/
+                       break;
+               case CANQUEUE_NOTIFY_NOUSR:
+//                     wake_up(&qends->endinfo.fileinfo.readq);
+//                     wake_up(&qends->endinfo.fileinfo.writeq);
+//                     wake_up(&qends->endinfo.fileinfo.emptyq);
+                       break;
+               case CANQUEUE_NOTIFY_DEAD_WANTED:
+               case CANQUEUE_NOTIFY_DEAD:
+                       if(canque_fifo_test_and_clear_fl(&qedge->fifo, READY))
+                               canque_edge_decref(qedge);
+                       break;
+               case CANQUEUE_NOTIFY_ATTACH:
+                       break;
+       }
+}
+
+/**
+ * canqueue_ends_init_kern - Linux userspace clients specific ends initialization
+ * @qends: pointer to the callback side ends structure
+ */
+int canqueue_ends_init_kern(struct canque_ends_t *qends)
+{
+       canqueue_ends_init_gen(qends);
+       qends->context=NULL;
+       init_waitqueue_head(&qends->endinfo.fileinfo.readq);
+       init_waitqueue_head(&qends->endinfo.fileinfo.writeq);
+       init_waitqueue_head(&qends->endinfo.fileinfo.emptyq);
+    #ifdef CAN_ENABLE_KERN_FASYNC
+       qends->endinfo.fileinfo.fasync=NULL;
+    #endif /*CAN_ENABLE_KERN_FASYNC*/
+
+       qends->notify=canqueue_notify_kern;
+       DEBUGQUE("canqueue_ends_init_kern\n");
+       return 0;
+}
+
+
+/**
+ * canque_get_inslot4id_wait_kern - find or wait for best outgoing edge and slot for given ID
+ * @qends: ends structure belonging to calling communication object
+ * @qedgep: place to store pointer to found edge
+ * @slotp: place to store pointer to  allocated slot
+ * @cmd: command type for slot
+ * @id: communication ID of message to send into edge
+ * @prio: optional priority of message
+ *
+ * Same as canque_get_inslot4id(), except, that it waits for free slot
+ * in case, that queue is full. Function is specific for Linux userspace clients.
+ * Return Value: If there is no usable edge negative value is returned.
+ */
+// int canque_get_inslot4id_wait_kern(struct canque_ends_t *qends,
+//     struct canque_edge_t **qedgep, struct canque_slot_t **slotp,
+//     int cmd, unsigned long id, int prio)
+// {
+//     int ret=-1;
+//     DEBUGQUE("canque_get_inslot4id_wait_kern for cmd %d, id %ld, prio %d\n",cmd,id,prio);
+//     wait_event_interruptible((qends->endinfo.fileinfo.writeq),
+//             (ret=canque_get_inslot4id(qends,qedgep,slotp,cmd,id,prio))!=-1);
+//     return ret;
+// }
+
+/**
+ * canque_get_outslot_wait_kern - receive or wait for ready slot for given ends
+ * @qends: ends structure belonging to calling communication object
+ * @qedgep: place to store pointer to found edge
+ * @slotp: place to store pointer to received slot
+ *
+ * The same as canque_test_outslot(), except it waits in the case, that there is
+ * no ready slot for given ends. Function is specific for Linux userspace clients.
+ * Return Value: Negative value informs, that there is no ready output
+ *     slot for given ends. Positive value is equal to the command
+ *     slot has been allocated by the input side.
+ */
+// int canque_get_outslot_wait_kern(struct canque_ends_t *qends,
+//     struct canque_edge_t **qedgep, struct canque_slot_t **slotp)
+// {
+//     int ret=-1;
+//     DEBUGQUE("canque_get_outslot_wait_kern\n");
+//     wait_event_interruptible((qends->endinfo.fileinfo.readq),
+//             (ret=canque_test_outslot(qends,qedgep,slotp))!=-1);
+//     return ret;
+// }
+
+/**
+ * canque_sync_wait_kern - wait for all slots processing
+ * @qends: ends structure belonging to calling communication object
+ * @qedge: pointer to edge
+ *
+ * Functions waits for ends transition into empty state.
+ * Return Value: Positive value indicates, that edge empty state has been reached.
+ *     Negative or zero value informs about interrupted wait or other problem.
+ */
+// int canque_sync_wait_kern(struct canque_ends_t *qends, struct canque_edge_t *qedge)
+// {
+//     int ret=-1;
+//     DEBUGQUE("canque_sync_wait_kern\n");
+//     wait_event_interruptible((qends->endinfo.fileinfo.emptyq),
+//             (ret=canque_fifo_test_fl(&qedge->fifo,EMPTY)?1:0));
+//     return ret;
+// }
+
+
+/**
+ * canque_fifo_init_kern - initialize one CAN FIFO
+ * @fifo: pointer to the FIFO structure
+ * @slotsnr: number of requested slots
+ *
+ * Return Value: The negative value indicates, that there is no memory
+ *     to allocate space for the requested number of the slots.
+ */
+int canque_fifo_init_kern(struct canque_fifo_t *fifo, int slotsnr)
+{
+       int size;
+       if(!slotsnr) slotsnr=MAX_BUF_LENGTH;
+       size=sizeof(struct canque_slot_t)*slotsnr;
+       fifo->entry=malloc(size);
+       if(!fifo->entry) return -1;
+       fifo->slotsnr=slotsnr;
+       return canque_fifo_init_slots(fifo);
+}
+
+/**
+ * canque_fifo_done_kern - frees slots allocated for CAN FIFO
+ * @fifo: pointer to the FIFO structure
+ */
+int canque_fifo_done_kern(struct canque_fifo_t *fifo)
+{
+       if(fifo->entry)
+               free(fifo->entry);
+       fifo->entry=NULL;
+       return 1;
+}
+
+
+/**
+ * canque_new_edge_kern - allocate new edge structure in the Linux kernel context
+ * @slotsnr: required number of slots in the newly allocated edge structure
+ *
+ * Return Value: Returns pointer to allocated slot structure or %NULL if
+ *     there is not enough memory to process operation.
+ */
+struct canque_edge_t *canque_new_edge_kern(int slotsnr)
+{
+       struct canque_edge_t *qedge;
+       qedge = (struct canque_edge_t *)malloc(sizeof(struct canque_edge_t));
+       if(qedge == NULL) return NULL;
+
+       memset(qedge,0,sizeof(struct canque_edge_t));
+       can_spin_lock_init(&qedge->fifo.fifo_lock);
+       if(canque_fifo_init_kern(&qedge->fifo, slotsnr)<0){
+               free(qedge);
+               DEBUGQUE("canque_new_edge_kern failed\n");
+               return NULL;
+       }
+       atomic_set(&qedge->edge_used,1);
+       qedge->filtid = 0;
+       qedge->filtmask = canque_filtid2internal(0l, (processlocal<2)? MSG_LOCAL:0);
+       qedge->edge_prio = 0;
+    #ifdef CAN_DEBUG
+       /* not exactly clean, but enough for debugging */
+       atomic_inc(&edge_num_cnt);
+       qedge->edge_num=atomic_read(&edge_num_cnt);
+    #endif /* CAN_DEBUG */
+       DEBUGQUE("canque_new_edge_kern %d\n",qedge->edge_num);
+       return qedge;
+}
+
+#ifdef USE_SYNC_DISCONNECT_EDGE_KERN
+
+/*not included in doc
+ * canqueue_disconnect_edge_kern - disconnect edge from communicating entities with wait
+ * @qends: ends structure belonging to calling communication object
+ * @qedge: pointer to edge
+ *
+ * Same as canqueue_disconnect_edge(), but tries to wait for state with zero
+ * use counter.
+ * Return Value: Negative value means, that edge is used and cannot
+ *     be disconnected yet. Operation has to be delayed.
+ */
+int canqueue_disconnect_edge_kern(struct canque_ends_t *qends, struct canque_edge_t *qedge)
+{
+       canque_fifo_set_fl(&qedge->fifo,BLOCK);
+       DEBUGQUE("canqueue_disconnect_edge_kern %d called\n",qedge->edge_num);
+       if(!canque_fifo_test_and_set_fl(&qedge->fifo,DEAD)){
+               canque_notify_bothends(qedge, CANQUEUE_NOTIFY_DEAD);
+
+               if(atomic_read(&qedge->edge_used)>0)
+                       atomic_dec(&qedge->edge_used);
+
+               DEBUGQUE("canqueue_disconnect_edge_kern %d waiting\n",qedge->edge_num);
+               wait_event((qends->endinfo.fileinfo.emptyq),
+                       (canqueue_disconnect_edge(qedge)>=0));
+
+               /*set_current_state(TASK_UNINTERRUPTIBLE);*/
+               /*schedule_timeout(HZ);*/
+               return 0;
+       } else {
+               DEBUGQUE("canqueue_disconnect_edge_kern cannot set DEAD\n");
+               return -1;
+       }
+}
+
+
+int canqueue_disconnect_list_kern(struct canque_ends_t *qends, struct list_head *list)
+{
+       struct canque_edge_t *edge;
+       can_spin_irqflags_t flags;
+       for(;;){
+               can_spin_lock_irqsave(&qends->ends_lock,flags);
+               if(list_empty(list)){
+                       can_spin_unlock_irqrestore(&qends->ends_lock,flags);
+                       return 0;
+               }
+               if(list == &qends->inlist)
+                       edge=list_entry(list->next,struct canque_edge_t,inpeers);
+               else
+                       edge=list_entry(list->next,struct canque_edge_t,outpeers);
+               atomic_inc(&edge->edge_used);
+               can_spin_unlock_irqrestore(&qends->ends_lock,flags);
+               if(canqueue_disconnect_edge_kern(qends, edge)>=0) {
+                       /* Free edge memory */
+                       canque_fifo_done_kern(&edge->fifo);
+                       free(edge);
+               }else{
+                       canque_notify_bothends(edge, CANQUEUE_NOTIFY_DEAD_WANTED);
+                       canque_edge_decref(edge);
+                       DEBUGQUE("canqueue_disconnect_list_kern in troubles\n");
+                       DEBUGQUE("the edge %d has usage count %d and flags %ld\n",edge->edge_num,atomic_read(&edge->edge_used),edge->fifo.fifo_flags);
+                       return -1;
+               }
+       }
+}
+
+#endif /*USE_SYNC_DISCONNECT_EDGE_KERN*/
+
+
+// int canqueue_ends_sync_all_kern(struct canque_ends_t *qends)
+// {
+//     struct canque_edge_t *qedge;
+//
+//     canque_for_each_inedge(qends, qedge){
+//             DEBUGQUE("canque_sync_wait_kern called for edge %d\n",qedge->edge_num);
+//             canque_sync_wait_kern(qends, qedge);
+//     }
+//     return 0;
+// }
+
+
+void canqueue_ends_dispose_postpone(struct canque_ends_t *qends)
+{
+       can_spin_irqflags_t flags;
+
+       can_spin_lock_irqsave(&canque_dead_func_lock, flags);
+       qends->ends_flags |= CAN_ENDSF_DEAD;
+       list_add(&qends->dead_peers,&canque_dead_ends);
+       can_spin_unlock_irqrestore(&canque_dead_func_lock, flags);
+       canque_dead_func(0);
+//     canque_dead_tasklet_schedule();
+}
+
+
+/**
+ * canqueue_ends_dispose_kern - finalizing of the ends structure for Linux kernel clients
+ * @qends: pointer to ends structure
+ * @sync: flag indicating, that user wants to wait for processing of all remaining
+ *     messages
+ *
+ * Return Value: Function should be designed such way to not fail.
+ */
+// int canqueue_ends_dispose_kern(struct canque_ends_t *qends, int sync)
+// {
+//     int delayed;
+//
+//     DEBUGQUE("canqueue_ends_dispose_kern\n");
+//     canqueue_block_inlist(qends);
+//     canqueue_block_outlist(qends);
+//
+//     /*Wait for sending of all pending messages in the output FIFOs*/
+//     if(sync)
+//             canqueue_ends_sync_all_kern(qends);
+//
+//     /* Finish or kill all outgoing edges listed in inends */
+//     delayed=canqueue_ends_kill_inlist(qends, 1);
+//     /* Kill all incoming edges listed in outends */
+//     delayed|=canqueue_ends_kill_outlist(qends);
+//
+// //  wake_up(&qends->endinfo.fileinfo.readq);
+// //  wake_up(&qends->endinfo.fileinfo.writeq);
+// //  wake_up(&qends->endinfo.fileinfo.emptyq);
+//
+//     if(delayed){
+//             canqueue_ends_dispose_postpone(qends);
+//
+//             DEBUGQUE("canqueue_ends_dispose_kern delayed\n");
+//             return 1;
+//     }
+//
+//     free(qends);
+//     DEBUGQUE("canqueue_ends_dispose_kern finished\n");
+//     return 0;
+// }
+
+void canqueue_kern_initialize()
+{
+       can_spin_lock_init(&canque_dead_func_lock);
+}
diff --git a/embedded/app/usbcan/can_queue.c b/embedded/app/usbcan/can_queue.c
new file mode 100644 (file)
index 0000000..9815fd0
--- /dev/null
@@ -0,0 +1,750 @@
+/* can_queue.c - CAN message queues
+ * Linux CAN-bus device driver.
+ * New CAN queues by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.3  17 Jun 2004
+ */
+
+#include "./can/can.h"
+#include "./can/can_sysdep.h"
+#include "./can/can_queue.h"
+
+/*
+ * Modifies Tx message processing
+ *  0 .. local message processing disabled
+ *  1 .. local messages disabled by default but can be enabled by canque_set_filt
+ *  2 .. local messages enabled by default, can be disabled by canque_set_filt
+ */
+extern int processlocal;
+
+atomic_t edge_num_cnt;
+
+// #define CAN_DEBUG
+#undef CAN_DEBUG
+
+#ifdef CAN_DEBUG
+       #define DEBUGQUE(fmt,args...) can_printk(KERN_ERR "can_queue (debug): " fmt,\
+       ##args)
+
+#else
+       #define DEBUGQUE(fmt,args...)
+#endif
+
+#define CANQUE_ROUNDROB 1
+
+
+/**
+ * canque_fifo_flush_slots - free all ready slots from the FIFO
+ * @fifo: pointer to the FIFO structure
+ *
+ * The caller should be prepared to handle situations, when some
+ * slots are held by input or output side slots processing.
+ * These slots cannot be flushed or their processing interrupted.
+ *
+ * Return Value: The nonzero value indicates, that queue has not been
+ *     empty before the function call.
+ */
+int canque_fifo_flush_slots(struct canque_fifo_t *fifo)
+{
+       int ret;
+       can_spin_irqflags_t flags;
+       struct canque_slot_t *slot;
+       can_spin_lock_irqsave(&fifo->fifo_lock, flags);
+       slot=fifo->head;
+       if(slot){
+               *fifo->tail=fifo->flist;
+               fifo->flist=slot;
+               fifo->head=NULL;
+               fifo->tail=&fifo->head;
+       }
+       canque_fifo_clear_fl(fifo,FULL);
+       ret=canque_fifo_test_and_set_fl(fifo,EMPTY)?0:1;
+       can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
+       return ret;
+}
+
+
+/**
+ * canque_fifo_init_slots - initializes slot chain of one CAN FIFO
+ * @fifo: pointer to the FIFO structure
+ *
+ * Return Value: The negative value indicates, that there is no memory
+ *     to allocate space for the requested number of the slots.
+ */
+int canque_fifo_init_slots(struct canque_fifo_t *fifo)
+{
+       struct canque_slot_t *slot;
+       int slotsnr=fifo->slotsnr;
+       if(!fifo->entry || !slotsnr) return -1;
+       slot=fifo->entry;
+       fifo->flist=slot;
+       while(--slotsnr){
+               slot->next=slot+1;
+               slot++;
+       }
+       slot->next=NULL;
+       fifo->head=NULL;
+       fifo->tail=&fifo->head;
+       canque_fifo_set_fl(fifo,EMPTY);
+       return 1;
+}
+
+/* atomic_dec_and_test(&qedge->edge_used);
+ void atomic_inc(&qedge->edge_used);
+ list_add_tail(struct list_head *new, struct list_head *head)
+ list_for_each(edge,qends->inlist);
+ list_entry(ptr, type, member)
+*/
+
+void __canque_edge_decref(struct canque_edge_t *edge)
+{
+       __canque_edge_decref_body(edge);
+}
+
+/**
+ * canque_get_inslot - finds one outgoing edge and allocates slot from it
+ * @qends: ends structure belonging to calling communication object
+ * @qedgep: place to store pointer to found edge
+ * @slotp: place to store pointer to  allocated slot
+ * @cmd: command type for slot
+ *
+ * Function looks for the first non-blocked outgoing edge in @qends structure
+ * and tries to allocate slot from it.
+ * Return Value: If there is no usable edge or there is no free slot in edge
+ *     negative value is returned.
+ */
+int canque_get_inslot(struct canque_ends_t *qends,
+       struct canque_edge_t **qedgep, struct canque_slot_t **slotp, int cmd)
+{
+       int ret=-2;
+       struct canque_edge_t *edge;
+
+       edge=canque_first_inedge(qends);
+       if(edge){
+               if(!canque_fifo_test_fl(&edge->fifo,BLOCK)){
+                       ret=canque_fifo_get_inslot(&edge->fifo, slotp, cmd);
+                       if(ret>0){
+                               *qedgep=edge;
+                               DEBUGQUE("canque_get_inslot cmd=%d found edge %d\n",cmd,edge->edge_num);
+                               return ret;
+
+                       }
+               }
+               canque_edge_decref(edge);
+       }
+       *qedgep=NULL;
+       DEBUGQUE("canque_get_inslot cmd=%d failed\n",cmd);
+       return ret;
+}
+
+/**
+ * canque_get_inslot4id - finds best outgoing edge and slot for given ID
+ * @qends: ends structure belonging to calling communication object
+ * @qedgep: place to store pointer to found edge
+ * @slotp: place to store pointer to  allocated slot
+ * @cmd: command type for slot
+ * @id: communication ID of message to send into edge
+ * @prio: optional priority of message
+ *
+ * Function looks for the non-blocked outgoing edge accepting messages
+ * with given ID. If edge is found, slot is allocated from that edge.
+ * The edges with non-zero mask are preferred over edges open to all messages.
+ * If more edges with mask accepts given message ID, the edge with
+ * highest priority below or equal to required priority is selected.
+ * Return Value: If there is no usable edge or there is no free slot in edge
+ *     negative value is returned.
+ */
+int canque_get_inslot4id(struct canque_ends_t *qends,
+       struct canque_edge_t **qedgep, struct canque_slot_t **slotp,
+       int cmd, unsigned long id, int prio)
+{
+       int ret=-2;
+       struct canque_edge_t *edge, *bestedge=NULL;
+
+       canque_for_each_inedge(qends, edge){
+               if(canque_fifo_test_fl(&edge->fifo,BLOCK))
+                       continue;
+               if((id^edge->filtid)&edge->filtmask)
+                       continue;
+               if(bestedge){
+                       if(bestedge->filtmask){
+                               if (!edge->filtmask) continue;
+                       } else {
+                               if(edge->filtmask){
+                                       canque_edge_decref(bestedge);
+                                       bestedge=edge;
+                                       canque_edge_incref(bestedge);
+                                       continue;
+                               }
+                       }
+                       if(bestedge->edge_prio<edge->edge_prio){
+                               if(edge->edge_prio>prio) continue;
+                       } else {
+                               if(bestedge->edge_prio<=prio) continue;
+                       }
+                       canque_edge_decref(bestedge);
+               }
+               bestedge=edge;
+               canque_edge_incref(bestedge);
+       }
+       if((edge=bestedge)!=NULL){
+               ret=canque_fifo_get_inslot(&edge->fifo, slotp, cmd);
+               if(ret>0){
+                       *qedgep=edge;
+                       DEBUGQUE("canque_get_inslot4id cmd=%d id=%ld prio=%d found edge %d\n",cmd,id,prio,edge->edge_num);
+                       return ret;
+               }
+               canque_edge_decref(bestedge);
+       }
+       *qedgep=NULL;
+       DEBUGQUE("canque_get_inslot4id cmd=%d id=%ld prio=%d failed\n",cmd,id,prio);
+       return ret;
+}
+
+
+/**
+ * canque_put_inslot - schedules filled slot for processing
+ * @qends: ends structure belonging to calling communication object
+ * @qedge: edge slot belong to
+ * @slot: pointer to the prepared slot
+ *
+ * Puts slot previously acquired by canque_get_inslot() or canque_get_inslot4id()
+ * function call into FIFO queue and activates edge processing if needed.
+ * Return Value: Positive value informs, that activation of output end
+ *     has been necessary
+ */
+int canque_put_inslot(struct canque_ends_t *qends,
+       struct canque_edge_t *qedge, struct canque_slot_t *slot)
+{
+       int ret;
+       ret=canque_fifo_put_inslot(&qedge->fifo,slot);
+       if(ret) {
+               canque_activate_edge(qends,qedge);
+               canque_notify_outends(qedge,CANQUEUE_NOTIFY_PROC);
+       }
+       canque_edge_decref(qedge);
+       DEBUGQUE("canque_put_inslot for edge %d returned %d\n",qedge->edge_num,ret);
+       return ret;
+}
+
+/**
+ * canque_abort_inslot - aborts preparation of the message in the slot
+ * @qends: ends structure belonging to calling communication object
+ * @qedge: edge slot belong to
+ * @slot: pointer to the previously allocated slot
+ *
+ * Frees slot previously acquired by canque_get_inslot() or canque_get_inslot4id()
+ * function call. Used when message copying into slot fails.
+ * Return Value: Positive value informs, that queue full state has been negated.
+ */
+int canque_abort_inslot(struct canque_ends_t *qends,
+       struct canque_edge_t *qedge, struct canque_slot_t *slot)
+{
+       int ret;
+       ret=canque_fifo_abort_inslot(&qedge->fifo,slot);
+       if(ret) {
+               canque_notify_outends(qedge,CANQUEUE_NOTIFY_SPACE);
+       }
+       canque_edge_decref(qedge);
+       DEBUGQUE("canque_abort_inslot for edge %d returned %d\n",qedge->edge_num,ret);
+       return ret;
+}
+
+/**
+ * canque_filter_msg2edges - sends message into all edges which accept its ID
+ * @qends: ends structure belonging to calling communication object
+ * @msg: pointer to CAN message
+ *
+ * Sends message to all outgoing edges connected to the given ends, which accepts
+ * message communication ID.
+ * Return Value: Returns number of edges message has been send to
+ */
+int canque_filter_msg2edges(struct canque_ends_t *qends, struct canmsg_t *msg)
+{
+       int destnr=0;
+       int ret;
+       unsigned long msgid;
+       struct canque_edge_t *edge;
+       struct canque_slot_t *slot;
+
+       DEBUGQUE("canque_filter_msg2edges for msg ID 0x%08lx and flags 0x%02x\n",
+                       msg->id, msg->flags);
+       msgid = canque_filtid2internal(msg->id, msg->flags);
+
+       canque_for_each_inedge(qends, edge) {
+               if(canque_fifo_test_fl(&edge->fifo,BLOCK))
+                       continue;
+               if((msgid^edge->filtid)&edge->filtmask)
+                       continue;
+               ret=canque_fifo_get_inslot(&edge->fifo, &slot, 0);
+               if(ret>0){
+                       slot->msg=*msg;
+                       destnr++;
+                       ret=canque_fifo_put_inslot(&edge->fifo,slot);
+                       if(ret) {
+                               canque_activate_edge(qends,edge);
+                               canque_notify_outends(edge,CANQUEUE_NOTIFY_PROC);
+                       }
+
+               }
+       }
+       DEBUGQUE("canque_filter_msg2edges sent msg ID %ld to %d edges\n",msg->id,destnr);
+       return destnr;
+}
+
+/**
+ * canque_test_outslot - test and retrieve ready slot for given ends
+ * @qends: ends structure belonging to calling communication object
+ * @qedgep: place to store pointer to found edge
+ * @slotp: place to store pointer to received slot
+ *
+ * Function takes highest priority active incoming edge and retrieves
+ * oldest ready slot from it.
+ * Return Value: Negative value informs, that there is no ready output
+ *     slot for given ends. Positive value is equal to the command
+ *     slot has been allocated by the input side.
+ */
+int canque_test_outslot(struct canque_ends_t *qends,
+       struct canque_edge_t **qedgep, struct canque_slot_t **slotp)
+{
+       can_spin_irqflags_t flags;
+       int prio;
+       struct canque_edge_t *edge;
+       int ret;
+
+       can_spin_lock_irqsave(&qends->ends_lock, flags);
+       for(prio=CANQUEUE_PRIO_NR;--prio>=0;){
+               while(!list_empty(&qends->active[prio])){
+                       edge=list_entry(qends->active[prio].next,struct canque_edge_t,activepeers);
+                       if(!canque_fifo_test_fl(&edge->fifo,DEAD)) {
+                               /* The first test on unlocked FIFO */
+                               if(canque_fifo_test_fl(&edge->fifo,EMPTY)) {
+                                       can_spin_lock(&edge->fifo.fifo_lock);
+                                       /* Test has to be repeated to ensure that EMPTY
+                                          state has not been nagated when locking FIFO */
+                                       if(canque_fifo_test_fl(&edge->fifo,EMPTY)) {
+                                               canque_fifo_set_fl(&edge->fifo,INACTIVE);
+                                               list_del(&edge->activepeers);
+                                               list_add(&edge->activepeers,&qends->idle);
+                                               can_spin_unlock(&edge->fifo.fifo_lock);
+                                               continue;
+                                       }
+                                       can_spin_unlock(&edge->fifo.fifo_lock);
+                               }
+                               canque_edge_incref(edge);
+                               can_spin_unlock_irqrestore(&qends->ends_lock, flags);
+                               *qedgep=edge;
+                               DEBUGQUE("canque_test_outslot found edge %d\n",edge->edge_num);
+                               ret=canque_fifo_test_outslot(&edge->fifo, slotp);
+                               if(ret>=0)
+                                       return ret;
+
+                               canque_edge_decref(edge);
+                               can_spin_lock_irqsave(&qends->ends_lock, flags);
+                       } else {
+                               can_spin_lock(&edge->fifo.fifo_lock);
+                               canque_fifo_set_fl(&edge->fifo,INACTIVE);
+                               list_del(&edge->activepeers);
+                               list_add(&edge->activepeers,&qends->idle);
+                               can_spin_unlock(&edge->fifo.fifo_lock);
+                       }
+               }
+       }
+       can_spin_unlock_irqrestore(&qends->ends_lock, flags);
+       *qedgep=NULL;
+//     DEBUGQUE("canque_test_outslot no ready slot\n");
+       return -1;
+}
+
+/**
+ * canque_free_outslot - frees processed output slot
+ * @qends: ends structure belonging to calling communication object
+ * @qedge: edge slot belong to
+ * @slot: pointer to the processed slot
+ *
+ * Function releases processed slot previously acquired by canque_test_outslot()
+ * function call.
+ * Return Value: Return value informs if input side has been notified
+ *     to know about change of edge state
+ */
+int canque_free_outslot(struct canque_ends_t *qends,
+       struct canque_edge_t *qedge, struct canque_slot_t *slot)
+{
+       int ret;
+       can_spin_irqflags_t flags;
+       ret=canque_fifo_free_outslot(&qedge->fifo, slot);
+       if(ret&CAN_FIFOF_EMPTY){
+               canque_notify_inends(qedge,CANQUEUE_NOTIFY_EMPTY);
+       }
+       if(ret&CAN_FIFOF_FULL)
+               canque_notify_inends(qedge,CANQUEUE_NOTIFY_SPACE);
+       can_spin_lock_irqsave(&qends->ends_lock, flags);
+       if((ret&CAN_FIFOF_EMPTY) || CANQUE_ROUNDROB ){
+               can_spin_lock(&qedge->fifo.fifo_lock);
+               if(canque_fifo_test_fl(&qedge->fifo,EMPTY)){
+                       canque_fifo_set_fl(&qedge->fifo,INACTIVE);
+                       list_del(&qedge->activepeers);
+                       list_add(&qedge->activepeers,&qends->idle);
+               } else{
+                       list_del(&qedge->activepeers);
+                       list_add_tail(&qedge->activepeers,&qends->active[qedge->edge_prio]);
+               }
+               can_spin_unlock(&qedge->fifo.fifo_lock);
+       }
+       can_spin_unlock_irqrestore(&qends->ends_lock, flags);
+       canque_edge_decref(qedge);
+       DEBUGQUE("canque_free_outslot for edge %d returned %d\n",qedge->edge_num,ret);
+       return ret;
+}
+
+/**
+ * canque_again_outslot - reschedule output slot to process it again later
+ * @qends: ends structure belonging to calling communication object
+ * @qedge: edge slot belong to
+ * @slot: pointer to the slot for re-processing
+ *
+ * Function reschedules slot previously acquired by canque_test_outslot()
+ * function call for second time processing.
+ * Return Value: Function cannot fail.
+ */
+int canque_again_outslot(struct canque_ends_t *qends,
+       struct canque_edge_t *qedge, struct canque_slot_t *slot)
+{
+       int ret;
+       ret=canque_fifo_again_outslot(&qedge->fifo, slot);
+       canque_edge_decref(qedge);
+       DEBUGQUE("canque_again_outslot for edge %d returned %d\n",qedge->edge_num,ret);
+       return ret;
+}
+
+/**
+ * canque_set_filt - sets filter for specified edge
+ * @qedge: pointer to the edge
+ * @filtid: ID to set for the edge
+ * @filtmask: mask used for ID match check
+ * @filtflags: required filer flags
+ *
+ * Return Value: Negative value is returned if edge is in the process of delete.
+ */
+int canque_set_filt(struct canque_edge_t *qedge,
+       unsigned long filtid, unsigned long filtmask, int filtflags)
+{
+       int ret;
+       can_spin_irqflags_t flags;
+
+       can_spin_lock_irqsave(&qedge->fifo.fifo_lock,flags);
+
+       if(!(filtflags&MSG_PROCESSLOCAL) && (processlocal<2))
+               filtflags |= MSG_LOCAL_MASK;
+
+       qedge->filtid=canque_filtid2internal(filtid, filtflags);
+       qedge->filtmask=canque_filtid2internal(filtmask, filtflags>>MSG_FILT_MASK_SHIFT);
+
+       if(canque_fifo_test_fl(&qedge->fifo,DEAD)) ret=-1;
+       else ret=canque_fifo_test_and_set_fl(&qedge->fifo,BLOCK)?1:0;
+
+       can_spin_unlock_irqrestore(&qedge->fifo.fifo_lock,flags);
+       if(ret>=0){
+               canque_notify_bothends(qedge,CANQUEUE_NOTIFY_FILTCH);
+       }
+       can_spin_lock_irqsave(&qedge->fifo.fifo_lock,flags);
+       if(!ret) canque_fifo_clear_fl(&qedge->fifo,BLOCK);
+       can_spin_unlock_irqrestore(&qedge->fifo.fifo_lock,flags);
+
+       DEBUGQUE("canque_set_filt for edge %d, ID %ld, mask %ld, flags %d returned %d\n",
+                 qedge->edge_num,filtid,filtmask,filtflags,ret);
+       return ret;
+}
+
+/**
+ * canque_flush - fluesh all ready slots in the edge
+ * @qedge: pointer to the edge
+ *
+ * Tries to flush all allocated slots from the edge, but there could
+ * exist some slots associated to edge which are processed by input
+ * or output side and cannot be flushed at this moment.
+ * Return Value: The nonzero value indicates, that queue has not been
+ *     empty before the function call.
+ */
+int canque_flush(struct canque_edge_t *qedge)
+{
+       int ret;
+       can_spin_irqflags_t flags;
+
+       ret=canque_fifo_flush_slots(&qedge->fifo);
+       if(ret){
+               canque_notify_inends(qedge,CANQUEUE_NOTIFY_EMPTY);
+               canque_notify_inends(qedge,CANQUEUE_NOTIFY_SPACE);
+               can_spin_lock_irqsave(&qedge->outends->ends_lock, flags);
+               can_spin_lock(&qedge->fifo.fifo_lock);
+               if(canque_fifo_test_fl(&qedge->fifo,EMPTY)){
+                       list_del(&qedge->activepeers);
+                       list_add(&qedge->activepeers,&qedge->outends->idle);
+               }
+               can_spin_unlock(&qedge->fifo.fifo_lock);
+               can_spin_unlock_irqrestore(&qedge->outends->ends_lock, flags);
+       }
+       DEBUGQUE("canque_flush for edge %d returned %d\n",qedge->edge_num,ret);
+       return ret;
+}
+
+/**
+ * canqueue_ends_init_gen - subsystem independent routine to initialize ends state
+ * @qends: pointer to the ends structure
+ *
+ * Return Value: Cannot fail.
+ */
+int canqueue_ends_init_gen(struct canque_ends_t *qends)
+{
+       int i;
+       qends->ends_flags=0;
+       for(i=CANQUEUE_PRIO_NR;--i>=0;){
+               INIT_LIST_HEAD(&qends->active[i]);
+       }
+       INIT_LIST_HEAD(&qends->idle);
+       INIT_LIST_HEAD(&qends->inlist);
+       INIT_LIST_HEAD(&qends->outlist);
+       can_spin_lock_init(&qends->ends_lock);
+       return 0;
+}
+
+
+/**
+ * canqueue_connect_edge - connect edge between two communication entities
+ * @qedge: pointer to edge
+ * @inends: pointer to ends the input of the edge should be connected to
+ * @outends: pointer to ends the output of the edge should be connected to
+ *
+ * Return Value: Negative value informs about failed operation.
+ */
+int canqueue_connect_edge(struct canque_edge_t *qedge, struct canque_ends_t *inends, struct canque_ends_t *outends)
+{
+       can_spin_irqflags_t flags;
+       if(qedge == NULL) return -1;
+       DEBUGQUE("canqueue_connect_edge %d\n",qedge->edge_num);
+       canque_edge_incref(qedge);
+       flags=canque_edge_lock_both_ends(inends, outends);
+       can_spin_lock(&qedge->fifo.fifo_lock);
+       qedge->inends=inends;
+       list_add(&qedge->inpeers,&inends->inlist);
+       qedge->outends=outends;
+       list_add(&qedge->outpeers,&outends->outlist);
+       list_add(&qedge->activepeers,&outends->idle);
+       can_spin_unlock(&qedge->fifo.fifo_lock);
+       canque_edge_unlock_both_ends(inends, outends, flags);
+       canque_notify_bothends(qedge, CANQUEUE_NOTIFY_ATTACH);
+
+       if(canque_fifo_test_and_set_fl(&qedge->fifo, READY))
+               canque_edge_decref(qedge);
+       return 0;
+}
+
+/**
+ * canqueue_disconnect_edge - disconnect edge from communicating entities
+ * @qedge: pointer to edge
+ *
+ * Return Value: Negative value means, that edge is used by somebody
+ *     other and cannot be disconnected. Operation has to be delayed.
+ */
+int canqueue_disconnect_edge(struct canque_edge_t *qedge)
+{
+       int ret;
+       can_spin_irqflags_t flags;
+       struct canque_ends_t *inends, *outends;
+
+       inends=qedge->inends;
+       outends=qedge->outends;
+
+       if(inends && outends) {
+               flags=canque_edge_lock_both_ends(inends, outends);
+       } else {
+               DEBUGQUE("canqueue_disconnect_edge called with not fully connected edge");
+               if(inends) can_spin_lock_irqsave(&inends->ends_lock,flags);
+               if(outends) can_spin_lock(&outends->ends_lock);
+               flags=0;
+       }
+
+       can_spin_lock(&qedge->fifo.fifo_lock);
+       if(atomic_read(&qedge->edge_used)==0) {
+               if(qedge->outends){
+                       list_del(&qedge->activepeers);
+                       mb(); /* memory barrier for list_empty use in canque_dead_func */
+                       list_del(&qedge->outpeers);
+                       qedge->outends=NULL;
+               }
+               if(qedge->inends){
+                       list_del(&qedge->inpeers);
+                       qedge->inends=NULL;
+               }
+               ret=1;
+       } else ret=-1;
+       can_spin_unlock(&qedge->fifo.fifo_lock);
+
+       if(inends && outends) {
+               canque_edge_unlock_both_ends(inends, outends, flags);
+       } else {
+               if(outends) can_spin_unlock(&outends->ends_lock);
+               if(inends) can_spin_unlock_irqrestore(&inends->ends_lock,flags);
+       }
+
+       DEBUGQUE("canqueue_disconnect_edge %d returned %d\n",qedge->edge_num,ret);
+       return ret;
+}
+
+
+/**
+ * canqueue_block_inlist - block slot allocation of all outgoing edges of specified ends
+ * @qends: pointer to ends structure
+ */
+void canqueue_block_inlist(struct canque_ends_t *qends)
+{
+       struct canque_edge_t *edge;
+
+        canque_for_each_inedge(qends, edge) {
+               canque_fifo_set_fl(&edge->fifo,BLOCK);
+       }
+}
+
+
+/**
+ * canqueue_block_outlist - block slot allocation of all incoming edges of specified ends
+ * @qends: pointer to ends structure
+ */
+void canqueue_block_outlist(struct canque_ends_t *qends)
+{
+       struct canque_edge_t *edge;
+
+        canque_for_each_outedge(qends, edge) {
+               canque_fifo_set_fl(&edge->fifo,BLOCK);
+       }
+}
+
+
+/**
+ * canqueue_ends_kill_inlist - sends request to die to all outgoing edges
+ * @qends: pointer to ends structure
+ * @send_rest: select, whether already allocated slots should be processed
+ *     by FIFO output side
+ *
+ * Return Value: Non-zero value means, that not all edges could be immediately
+ *     disconnected and that ends structure memory release has to be delayed
+ */
+int canqueue_ends_kill_inlist(struct canque_ends_t *qends, int send_rest)
+{
+       struct canque_edge_t *edge;
+
+       canque_for_each_inedge(qends, edge){
+               canque_notify_bothends(edge, CANQUEUE_NOTIFY_DEAD_WANTED);
+               if(send_rest){
+                       canque_edge_incref(edge);
+                       if(!canque_fifo_test_and_set_fl(&edge->fifo, FREEONEMPTY)){
+                               if(!canque_fifo_test_fl(&edge->fifo, EMPTY))
+                                       continue;
+                               if(!canque_fifo_test_and_clear_fl(&edge->fifo, FREEONEMPTY))
+                                       continue;
+                       }
+                       canque_edge_decref(edge);
+               }
+       }
+       return list_empty(&qends->inlist)?0:1;
+}
+
+
+/**
+ * canqueue_ends_kill_outlist - sends request to die to all incoming edges
+ * @qends: pointer to ends structure
+ *
+ * Return Value: Non-zero value means, that not all edges could be immediately
+ *     disconnected and that ends structure memory release has to be delayed
+ */
+int canqueue_ends_kill_outlist(struct canque_ends_t *qends)
+{
+       struct canque_edge_t *edge;
+
+       canque_for_each_outedge(qends, edge){
+               canque_notify_bothends(edge, CANQUEUE_NOTIFY_DEAD_WANTED);
+       }
+       return list_empty(&qends->outlist)?0:1;
+}
+
+
+/**
+ * canqueue_ends_filt_conjuction - computes conjunction of incoming edges filters filters
+ * @qends: pointer to ends structure
+ * @filt: pointer the filter structure filled by computed filters conjunction
+ *
+ * Return Value: Number of incoming edges
+ */
+int canqueue_ends_filt_conjuction(struct canque_ends_t *qends, struct canfilt_t *filt)
+{
+       struct canque_edge_t *edge;
+       int cnt=0;
+       unsigned long filtid=0;
+       unsigned long filtmask=~0;
+       unsigned long local_only=canque_filtid2internal(0,MSG_LOCAL);
+
+       canque_for_each_inedge(qends, edge){
+               /* skip edges processing only local messages */
+               if(edge->filtid & edge->filtmask & local_only)
+                       continue;
+
+               if(!cnt++)
+                       filtid = edge->filtid;
+               else
+                       filtmask &= ~(filtid ^ edge->filtid);
+
+               filtmask &= edge->filtmask;
+       }
+
+       filt->id = filtid & MSG_ID_MASK;
+       filt->mask = filtmask & MSG_ID_MASK;
+       filtid >>= 28;
+       filtmask >>= 28;
+       filt->flags = filtid & MSG_EXT;
+       if(filtmask & (MSG_EXT))
+               filt->flags |= MSG_EXT_MASK;
+       if(filtid & (MSG_RTR<<1))
+               filt->flags |= MSG_RTR<<1;
+       if(filtmask & (MSG_RTR<<1))
+               filt->flags |= MSG_RTR_MASK;
+       return cnt;
+}
+
+
+/**
+ * canqueue_ends_flush_inlist - flushes all messages in incoming edges
+ * @qends: pointer to ends structure
+ *
+ * Return Value: Negative value informs about unsuccessful result
+ */
+int canqueue_ends_flush_inlist(struct canque_ends_t *qends)
+{
+       struct canque_edge_t *edge;
+
+       canque_for_each_inedge(qends, edge){
+               canque_flush(edge);
+       }
+       return 0;
+}
+
+
+/**
+ * canqueue_ends_flush_outlist - flushes all messages in outgoing edges
+ * @qends: pointer to ends structure
+ *
+ * Return Value: Negative value informs about unsuccessful result
+ */
+int canqueue_ends_flush_outlist(struct canque_ends_t *qends)
+{
+       struct canque_edge_t *edge;
+
+       canque_for_each_outedge(qends, edge){
+               canque_flush(edge);
+       }
+       return 0;
+}
+
+
+
+
diff --git a/embedded/app/usbcan/devcommon.c b/embedded/app/usbcan/devcommon.c
new file mode 100644 (file)
index 0000000..eada97b
--- /dev/null
@@ -0,0 +1,131 @@
+/* devcommon.c - common device code
+ * Linux CAN-bus device driver.
+ * New CAN queues by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.3  17 Jun 2004
+ */
+
+#include "./can/can.h"
+#include "./can/can_sysdep.h"
+#include "./can/can_queue.h"
+#include "./can/main.h"
+#include "./can/devcommon.h"
+
+#ifdef CAN_WITH_RTL
+static inline
+void canqueue_wake_chip_worker(struct canque_ends_t *qends, struct canchip_t *chip, struct msgobj_t *obj)
+{
+       if(qends->endinfo.chipinfo.worker_thread){
+               can_msgobj_set_fl(obj,WORKER_WAKE);
+               pthread_kill(qends->endinfo.chipinfo.worker_thread,RTL_SIGNAL_WAKEUP);
+               rtl_schedule();
+       } else {
+               set_bit(MSGOBJ_TX_REQUEST_b,&chip->pend_flags);
+               if(chip->worker_thread) {
+                       set_bit(MSGOBJ_WORKER_WAKE_b,&chip->pend_flags);
+                       pthread_kill(chip->worker_thread,RTL_SIGNAL_WAKEUP);
+                       rtl_schedule();
+               }
+       }
+}
+
+#endif /*CAN_WITH_RTL*/
+
+
+/**
+ * canqueue_notify_chip - notification callback handler for CAN chips ends of queues
+ * @qends: pointer to the callback side ends structure
+ * @qedge: edge which invoked notification
+ * @what: notification type
+ *
+ * This function has to deal with more possible cases. It can be called from
+ * the kernel or interrupt context for Linux only compilation of driver.
+ * The function can be called from kernel context or RT-Linux thread context
+ * for mixed mode Linux/RT-Linux compilation.
+ */
+void canqueue_notify_chip(struct canque_ends_t *qends, struct canque_edge_t *qedge, int what)
+{
+       struct canchip_t *chip=qends->endinfo.chipinfo.chip;
+       struct msgobj_t *obj=qends->endinfo.chipinfo.msgobj;
+
+       DEBUGMSG("canqueue_notify_chip for edge %d and event %d\n",qedge->edge_num,what);
+       switch(what){
+               /*case CANQUEUE_NOTIFY_EMPTY:*/
+               /*case CANQUEUE_NOTIFY_SPACE:*/
+               /*case CANQUEUE_NOTIFY_NOUSR:
+                       wake_up(&qends->endinfo.chipinfo.daemonq);
+                       break;*/
+               case CANQUEUE_NOTIFY_PROC:
+                   #ifndef CAN_WITH_RTL
+                       /*wake_up(&qends->endinfo.chipinfo.daemonq);*/
+                       chip->chipspecops->wakeup_tx(chip, obj);
+                   #else /*CAN_WITH_RTL*/
+                       can_msgobj_set_fl(obj,TX_REQUEST);
+                       canqueue_wake_chip_worker(qends, chip, obj);
+                   #endif /*CAN_WITH_RTL*/
+                       break;
+               case CANQUEUE_NOTIFY_DEAD_WANTED:
+               case CANQUEUE_NOTIFY_DEAD:
+                       if(canque_fifo_test_and_clear_fl(&qedge->fifo, READY))
+                               canque_edge_decref(qedge);
+                       break;
+               case CANQUEUE_NOTIFY_ATTACH:
+                       break;
+               case CANQUEUE_NOTIFY_FILTCH:
+                       if(!chip->chipspecops->filtch_rq)
+                               break;
+                   #ifndef CAN_WITH_RTL
+                       chip->chipspecops->filtch_rq(chip, obj);
+                   #else /*CAN_WITH_RTL*/
+                       can_msgobj_set_fl(obj,FILTCH_REQUEST);
+                       canqueue_wake_chip_worker(qends, chip, obj);
+                   #endif /*CAN_WITH_RTL*/
+
+                       break;
+       }
+}
+
+
+/**
+ * canqueue_ends_init_chip - CAN chip specific ends initialization
+ * @qends: pointer to the ends structure
+ * @chip: pointer to the corresponding CAN chip structure
+ * @obj: pointer to the corresponding message object structure
+ */
+int canqueue_ends_init_chip(struct canque_ends_t *qends, struct canchip_t *chip, struct msgobj_t *obj)
+{
+       int ret;
+       ret=canqueue_ends_init_gen(qends);
+       if(ret<0) return ret;
+
+       qends->context=NULL;
+    #ifndef CAN_WITH_RTL
+       init_waitqueue_head(&qends->endinfo.chipinfo.daemonq);
+    #endif /*CAN_WITH_RTL*/
+       qends->endinfo.chipinfo.chip=chip;
+       qends->endinfo.chipinfo.msgobj=obj;
+       qends->notify=canqueue_notify_chip;
+
+       DEBUGMSG("canqueue_ends_init_chip\n");
+       return 0;
+}
+
+
+/**
+ * canqueue_ends_done_chip - finalizing of the ends structure for CAN chips
+ * @qends: pointer to ends structure
+ *
+ * Return Value: Function should be designed such way to not fail.
+ */
+int canqueue_ends_done_chip(struct canque_ends_t *qends)
+{
+       int delayed;
+
+       /* Finish or kill all outgoing edges listed in inends */
+       delayed=canqueue_ends_kill_inlist(qends, 1);
+       /* Kill all incoming edges listed in outends */
+       delayed|=canqueue_ends_kill_outlist(qends);
+
+       return delayed;
+}
diff --git a/embedded/app/usbcan/finish.c b/embedded/app/usbcan/finish.c
new file mode 100644 (file)
index 0000000..fad2c05
--- /dev/null
@@ -0,0 +1,136 @@
+/* finish.c - finalization of the driver operation
+ * Linux CAN-bus device driver.
+ * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
+ * Rewritten for new CAN queues by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.3  17 Jun 2004
+ */
+
+#include "./can/can.h"
+#include "./can/can_sysless.h"
+#include "./can/main.h"
+#include "./can/devcommon.h"
+#include "./can/finish.h"
+#include "./can/setup.h"
+
+
+/**
+ * msgobj_done - destroys one CAN message object
+ * @obj: pointer to CAN message object structure
+ */
+void msgobj_done(struct msgobj_t *obj)
+{
+       int delayed=0;
+       if(obj->qends) {
+               delayed=canqueue_ends_done_chip(obj->qends);
+               if(delayed < 0)
+                       CANMSG("msgobj_done: problem with chip queue ends\n");
+       }
+
+       if((obj->hostchip) && (obj->object>0)) {
+               if(obj->hostchip->msgobj[obj->object-1] == obj)
+                       obj->hostchip->msgobj[obj->object-1]=NULL;
+               else
+                       CANMSG("msgobj_done: not registered in the canchip_t\n");
+               obj->hostchip=NULL;
+       }
+
+       if((obj->minor>=0)) {
+               if(objects_p[obj->minor] == obj)
+                       objects_p[obj->minor] = NULL;
+               else
+                       CANMSG("msgobj_done: not registered as minor\n");
+       }
+
+//     del_timer_sync(&obj->tx_timeout);
+
+       if(obj->qends) {
+               /*delayed free could be required there in the future,
+                 actual use patter cannot generate such situation*/
+               if(!delayed) {
+                       free(obj->qends);
+               }
+       }
+       obj->qends=NULL;
+}
+
+
+/**
+ * canchip_done - destroys one CAN chip representation
+ * @chip: pointer to CAN chip structure
+ */
+void canchip_done(struct canchip_t *chip)
+{
+
+       int i;
+       struct msgobj_t *obj;
+
+       if(chip->flags & CHIP_ATTACHED)
+               chip->chipspecops->release_chip(chip);
+
+       if((chip->hostdevice) && (chip->chip_idx>=0)) {
+               if(chip->hostdevice->chip[chip->chip_idx] == chip)
+                       chip->hostdevice->chip[chip->chip_idx] = NULL;
+               else
+                       CANMSG("canchip_done: not registered in hostdevice\n");
+       }
+
+// Not using interrupts
+//     can_chip_free_irq(chip);
+
+//     can_synchronize_irq(chip->chip_irq);
+
+       for(i=0; i<chip->max_objects; i++){
+               if((obj=chip->msgobj[i])==NULL)
+                       continue;
+               msgobj_done(obj);
+               free(obj);
+       }
+
+       free(chip->chipspecops);
+       chip->chipspecops=NULL;
+
+}
+
+/**
+ * candevice_done - destroys representation of one CAN device/board
+ * @candev: pointer to CAN device/board structure
+ */
+void candevice_done(struct candevice_t *candev)
+{
+       int i;
+       struct canchip_t *chip;
+
+       for(i=0; i<candev->nr_all_chips; i++){
+               if((chip=candev->chip[i])==NULL)
+                       continue;
+               canchip_done(chip);
+               free(chip);
+
+       }
+       if(candev->flags & CANDEV_IO_RESERVED) {
+               candev->hwspecops->release_io(candev);
+               candev->flags &= ~CANDEV_IO_RESERVED;
+       }
+       free(candev->hwspecops);
+       candev->hwspecops=NULL;
+}
+
+/**
+ * candevice_done - destroys representation of all CAN devices/boards
+ * @canhw: pointer to the root of all CAN hardware representation
+ */
+void canhardware_done(struct canhardware_t *canhw)
+{
+       int i;
+       struct candevice_t *candev;
+
+       for(i=0; i<canhw->nr_boards; i++){
+               if((candev=canhw->candevice[i])==NULL)
+                       continue;
+               candevice_done(candev);
+               free(candev);
+       }
+
+}
diff --git a/embedded/app/usbcan/main.c b/embedded/app/usbcan/main.c
new file mode 100644 (file)
index 0000000..fd12f59
--- /dev/null
@@ -0,0 +1,462 @@
+#include <stdio.h>
+#include <string.h>
+#include <cpu_def.h>
+#include <system_def.h>
+#include <lt_timer.h>
+#include <local_config.h>
+#include <usb/usbdebug.h>
+#include <usb/usb.h>
+#include <usb/lpc.h>
+#include <usb/usb_srq.h>
+#include <mem_loc.h>
+#include <keyval_id.h>
+#include <hal_machperiph.h>
+#include <keyval_loc.h>
+#include <lpciap.h>
+#include <lpciap_kvpb.h>
+
+#include <endian.h>
+#if __BYTE_ORDER == __BIG_ENDIAN
+  #include <byteswap.h>
+#endif
+
+#include "./can/can.h"
+#include "./can/sja1000p.h"
+#include "./can/main.h"
+
+// #include "./can/can_sysdep.h"
+#include "./can/modparms.h"
+#include "./can/devcommon.h"
+
+#include "./can/ul_usb1.h"
+//#include "./can/setup.h"
+
+#include "./usb/usb_vend.h"
+
+#define MASK_EP1RX  0x01
+#define MASK_EP1TX  0x02
+
+#define CAN_OP_MASK 0x80
+#define CAN_OP_READ 0x80
+#define CAN_OP_WRITE 0x00
+
+#ifdef USB_MAX_PACKET
+       #undef USB_MAX_PACKET
+       #define USB_MAX_PACKET 16
+#endif
+/***********************************************************************
+ * Note:
+ * Comparing to LinCAN, there is no need to sleep for processes
+ * because the degree of filling of fifo from the client side
+ * is solved in main cycle (no new messages are accepted when full)
+ * and on the server side by speed of USB interface. FIFO in edge
+ * from SJA chip to USB interface should never be filled.
+ ***********************************************************************/
+
+/***********************************************************************
+ * Note:
+ * Code is wittingly complex in order to ease future changes in hardware
+ * configuration and to make it as much similar as the code of LinCAN
+ ***********************************************************************/
+
+LT_TIMER_DEC(lt_10msec)
+LT_TIMER_IMP(lt_10msec)
+LT_TIMER_DEC(lt_100msec)
+LT_TIMER_IMP(lt_100msec)
+LT_TIMER_DEC(lt_2sec)
+LT_TIMER_IMP(lt_2sec)
+
+typedef void (*FNC)(); //function ptr
+
+/***********************************************************************
+       * global variables
+       ***********************************************************************/
+
+
+usb_device_t usb_device;
+
+usb_ep_t eps[2];
+unsigned char ep1_rx_buff[USB_MAX_PACKET];
+unsigned char ep1_tx_buff[USB_MAX_PACKET];
+uint8_t timer_str,timer_rx_off,timer_tx_off,timer_configured;
+volatile uint8_t bootloader_run;
+
+uint8_t vendor_ret;
+
+int processlocal;
+
+int baudrate[MAX_TOT_CHIPS];
+struct canhardware_t canhardware;
+struct canhardware_t *hardware_p=&canhardware;
+struct canchip_t *chips_p[MAX_TOT_CHIPS];
+struct msgobj_t *objects_p[MAX_TOT_MSGOBJS];
+
+struct canuser_t *canuser;
+
+extern int init_chip_struct(struct candevice_t *candev, int chipnr, int irq, long baudrate);
+extern int register_chip_struct(struct canchip_t *chip, int minorbase);
+extern int register_obj_struct(struct msgobj_t *obj, int minorbase);
+
+/***********************************************************************
+ * IF SOMETHING BAD HAPPENED
+ ***********************************************************************/
+
+int sys_err(){
+  unsigned char i=0;
+
+  while(1) {
+    if (lt_100msec_expired(100)) {
+      i++;
+      if (i&1) {
+        SET_OUT_PIN(LED_PORT,LED_ERR);
+      } else {
+        CLR_OUT_PIN(LED_PORT,LED_ERR);
+      }
+     #ifdef WATCHDOG_ENABLED
+      watchdog_feed();
+     #endif /* WATCHDOG_ENABLED */
+    }
+  }
+}
+
+/***********************************************************************
+ * Routine for visible LED blinking (on USB transmission)
+ ***********************************************************************/
+
+void timer_10ms(void)
+{
+  if (timer_tx_off!=0) timer_tx_off--;
+  else SET_OUT_PIN(LED_PORT,LED1_BIT);
+  if (timer_rx_off!=0) timer_rx_off--;
+  else SET_OUT_PIN(LED_PORT,LED2_BIT);
+/*  if (timer_configured!=0) timer_configured--;
+  else {
+    timer_configured=20;
+               CLR_OUT_PIN(LED_PORT,LED1_BIT);
+               CLR_OUT_PIN(LED_PORT,LED2_BIT);
+               timer_rx_off=timer_tx_off=5;
+  }*/
+}
+
+/***********************************************************************
+ * Main routine
+ ***********************************************************************/
+
+int main(void)
+{
+       struct candevice_t *candev;
+       struct canchip_t *chip=NULL;
+       struct msgobj_t *obj;
+       struct canque_ends_t *qends;
+       struct canque_edge_t *edge,*qedge;
+       struct canque_slot_t *slot;
+       struct canmsg_t canmsg;
+       can_spin_irqflags_t iflags;
+
+       int chipnr,bd;
+       int i,size,m=0;
+
+       CANMSG("Starting USBCAN module firmware...\n");
+
+//     volatile int i=0;
+       bootloader_run=0;
+       /***********************************/
+       lt_10msec_init();
+       lt_100msec_init();
+       lt_2sec_init();
+
+       SET_OUT_PIN(LED_PORT,LED_ERR);
+       CLR_OUT_PIN(LED_PORT,LED_GP);
+
+       if (USB_MAX_PACKET<16){
+               CANMSG("Maximum packet size less than 16B (is %dB)\n",USB_MAX_PACKET);
+               sys_err();
+       }
+
+       /***********************************************************************
+        * CAN device initialization - device side (adapted from LinCAN setup.c)
+        ***********************************************************************/
+
+       can_init();
+
+       DEBUGMSG("Initiating CAN device initialization\n");
+       baudrate[0]=1000;
+
+       canqueue_kern_initialize();
+
+       hardware_p->nr_boards=1;
+
+       candev=(struct candevice_t *)malloc(sizeof(struct candevice_t));
+       if (!candev){
+               CANMSG("No space left in memory\n");
+               sys_err();
+       }
+       memset(candev, 0, sizeof(struct candevice_t));
+
+       hardware_p->candevice[0]=candev;
+       candev->candev_idx=0;
+       candev->io_addr=0;
+       candev->dev_base_addr=0;
+
+       candev->hwspecops=(struct hwspecops_t *)malloc(sizeof(struct hwspecops_t));
+       if (!candev->hwspecops){
+               CANMSG("No space left in memory\n");
+               sys_err();
+       }
+       memset(candev->hwspecops, 0, sizeof(struct hwspecops_t));
+
+       ul_usb1_register(candev->hwspecops);
+
+       bd=baudrate[0];
+       if (candev->hwspecops->init_hw_data(candev)){
+               CANMSG("HW data could not be initialized\n");
+               sys_err();
+       }
+       /* Alocate and initialize the chip structures */
+       for (chipnr=0; chipnr < candev->nr_all_chips; chipnr++) {
+/*             if(chipnr<irqnum)
+                       irqsig=irq[*irq_param_idx_p+chipnr];*/
+               if (init_chip_struct(candev, chipnr, 0, bd*1000)){
+                       CANMSG("Chip structure could not be initialized\n");
+                       sys_err();
+               }
+       }
+       for (chipnr=0; chipnr < candev->nr_all_chips; chipnr++) {
+               struct canchip_t *chip=candev->chip[chipnr];
+               int objnr;
+
+               register_chip_struct(chip, m);
+
+               for (objnr=0; objnr<chip->max_objects; objnr++) {
+                       register_obj_struct(chip->msgobj[objnr], m);
+                       if(m>=0) m++;
+               }
+       }
+       if (candev->hwspecops->request_io(candev))
+               sys_err();
+       candev->flags|=CANDEV_IO_RESERVED;
+       if (candev->hwspecops->reset(candev))
+               sys_err();
+       for(chipnr=0; chipnr<candev->nr_all_chips; chipnr++) {
+               if((chip=candev->chip[chipnr])==NULL)
+                       continue;
+
+               if(chip->chipspecops->attach_to_chip(chip)<0) {
+//                     CANMSG("Initial attach to the chip HW failed\n");
+                       sys_err();
+               }
+
+               chip->flags |= CHIP_ATTACHED;
+
+// Interrupts from chip are served in main cycle
+/*             if(can_chip_setup_irq(chip)<0) {
+//                     CANMSG("Error to setup chip IRQ\n");
+                       sys_err();
+               }*/
+       }
+
+       if (candev->flags & CANDEV_PROGRAMMABLE_IRQ)
+               if (candev->hwspecops->program_irq(candev)){
+//                     CANMSG("Error to program board interrupt\n");
+                       sys_err();
+               }
+
+       /***********************************************************************
+        * CAN device initialization - client side (adapted from LinCAN open.c)
+        ***********************************************************************/
+
+       chip=candev->chip[0];
+       obj=chip->msgobj[0];
+       atomic_inc(&obj->obj_used);
+       can_msgobj_set_fl(obj,OPENED);
+
+       if (chip->flags & CHIP_CONFIGURED)
+               DEBUGMSG("Device is already configured.\n");
+       else {
+               if (chip->chipspecops->chip_config(chip))
+                       CANMSG("Error configuring chip.\n");
+               else
+                       chip->flags |= CHIP_CONFIGURED;
+
+               if (chip->chipspecops->pre_read_config(chip,obj)<0)
+                       CANMSG("Error initializing chip for receiving\n");
+
+       } /* End of chip configuration */
+
+       canuser = (struct canuser_t *)malloc(sizeof(struct canuser_t));
+       if(canuser == NULL) sys_err();
+       canuser->flags=0;
+//     canuser->userinfo.fileinfo.file = file;
+       canuser->msgobj = obj;
+//     canuser->magic = CAN_USER_MAGIC;
+//     file->private_data = canuser;
+
+       qends = (struct canque_ends_t *)malloc(sizeof(struct canque_ends_t));
+       if(qends == NULL) sys_err();
+       canqueue_ends_init_kern(qends);
+       canuser->qends = qends;
+
+       /*required to synchronize with RT-Linux context*/
+       can_spin_lock_irqsave(&canuser_manipulation_lock, iflags);
+       list_add(&canuser->peers, &obj->obj_users);
+       can_spin_unlock_irqrestore(&canuser_manipulation_lock, iflags);
+
+       if(canqueue_connect_edge(edge=canque_new_edge_kern(MAX_BUF_LENGTH),
+               canuser->qends, obj->qends)<0) sys_err();
+
+       if(canqueue_connect_edge(canuser->rx_edge0=canque_new_edge_kern(MAX_BUF_LENGTH),
+               obj->qends, canuser->qends)<0) sys_err();
+       /*FIXME: more generic model should be used there*/
+       canque_edge_decref(canuser->rx_edge0);
+       canque_edge_decref(edge);
+
+
+       /***********************************************************************
+        * USB Init
+        ***********************************************************************/
+
+       memset( &usb_device, 0, sizeof( usb_device));
+       usb_device.id = 1;
+       usb_device.init = usb_lpc_init;
+       usb_debug_set_level(DEBUG_LEVEL_NONE);
+       usb_device.cntep = 3;
+       usb_device.ep = eps;
+
+       eps[0].max_packet_size = USB_MAX_PACKET;
+       eps[1].max_packet_size = USB_MAX_PACKET;
+       eps[0].epnum = 0x01;
+       eps[1].epnum = 0x81;
+       eps[0].event_mask = 0x04;
+       eps[1].event_mask = 0x08;
+       eps[0].udev = &usb_device;
+       eps[1].udev = &usb_device;
+
+  usb_device.vendor_fnc=usbcan_vendor;
+
+       usb_init(&usb_device);
+       usb_connect(&usb_device);
+       usb_device.ep_events |= MASK_EP1TX;
+
+       /***********************************************************************
+        * Start
+        ***********************************************************************/
+
+  timer_rx_off=timer_tx_off=timer_str=timer_configured=0;
+       while (1) {
+
+               usb_check_events(&usb_device);
+               usb_control_response(&usb_device);
+
+               if (!(IO0PIN&P0_SJA1000_INT_PIN)) //INT PIN is inverted
+                       chip->chipspecops->irq_handler(0,chip);
+
+               if (usb_device.ep_events & MASK_EP1RX) {  //EP1RX - data waiting to receive
+                       uint8_t val;
+                       if (canque_get_inslot(qends, &qedge, &slot, 0)>=0){ //Free slot obtained
+                               size=usb_udev_read_endpoint(&eps[0],ep1_rx_buff,16);
+                               if (size==16){
+                                       uint16_t msgflags;
+                                       uint32_t msgid;
+                                       canmsg.cob=0;
+                                       canmsg.length=*(uint8_t *)(ep1_rx_buff+1);
+                                       if (canmsg.length > CAN_MSG_LENGTH)
+                                               canmsg.length=CAN_MSG_LENGTH;
+                                       msgflags=*(uint16_t *)(ep1_rx_buff+2);
+                                       msgid=*(uint32_t *)(ep1_rx_buff+4);
+                                       #if __BYTE_ORDER == __BIG_ENDIAN
+                                               msgflags  = bswap_16( msgflags);
+                                               msgid  = bswap_32( msgid);
+                                       #endif
+                                       canmsg.flags=msgflags;
+                                       canmsg.id=msgid;
+
+                                       for (i=0;i<canmsg.length;i++){
+                                               canmsg.data[i]=*(unsigned char*)(ep1_rx_buff+8+i);
+                                       }
+                                       for (;i<CAN_MSG_LENGTH;i++){
+                                               canmsg.data[i]=0;
+                                       }
+                                       /* Automatic selection of extended format if ID>2047 */
+                                       if (canmsg.id & ~0x7ffl & MSG_ID_MASK ) canmsg.flags |= MSG_EXT;
+                                       /* has been dependent on "extended" option */
+                                       slot->msg=canmsg;
+                                       canque_put_inslot(qends, qedge, slot);
+                               }
+                               else
+                                       canque_abort_inslot(qends,qedge,slot);
+                               timer_rx_off=50;        //rosviceni diody pri prijmu
+                               CLR_OUT_PIN(LED_PORT,LED2_BIT);
+                               usb_device.ep_events &= ~MASK_EP1RX;
+                       }
+
+
+/*                     if (size==2){
+                               if (((*data)&CAN_OP_MASK)==CAN_OP_READ){ // Get data from CAN device and return to caller
+                                       can_read((*data) & 0x7F,&val);
+                                       *(data+1)=val;
+                                       usb_udev_write_endpoint(&eps[1],(unsigned char *)data,size);
+                                       timer_rx_off=50;        //rosviceni diody pri prijmu
+                                       CLR_OUT_PIN(LED_PORT,LED2_BIT);
+                                       usb_can_send=0;
+                               }
+                               if (((*data)&CAN_OP_MASK)==CAN_OP_WRITE){ // Save data to CAN device
+                                       can_write((*data)&(~CAN_OP_MASK),data+1);
+                                       timer_tx_off=50;                //rozsviceni diod pri vysilani
+                                       CLR_OUT_PIN(LED_PORT,LED1_BIT);
+                               }
+                       }*/
+               }
+
+               if(usb_device.ep_events & MASK_EP1TX){ //EP1TX - data transmitted
+                       if(canque_test_outslot(qends, &qedge, &slot)>=0){
+                               DEBUGMSG("CAN message ready to send over usb\n");
+                               uint16_t msgflags;
+                               uint32_t msgid;
+
+                               *(uint8_t *)(ep1_tx_buff)=0;
+                               *(uint8_t *)(ep1_tx_buff+1)=slot->msg.length;
+
+                               msgflags=slot->msg.flags;
+                               msgid=slot->msg.id;
+                               #if __BYTE_ORDER == __BIG_ENDIAN
+                                       msgflags  = bswap_16( msgflags);
+                                       msgid  = bswap_32( msgid);
+                               #endif
+
+                               *(uint16_t *)(ep1_tx_buff+2)=msgflags;
+                               *(uint32_t *)(ep1_tx_buff+4)=msgid;
+                               for (i=0;i<slot->msg.length;i++){
+                                       *(uint8_t *)(ep1_tx_buff+8+i)=slot->msg.data[i];
+                               }
+                               for (;i<CAN_MSG_LENGTH;i++){
+                                       *(uint8_t *)(ep1_tx_buff+8+i)=0;
+                               }
+                               usb_udev_write_endpoint(&eps[1],ep1_tx_buff,16);
+
+                               canque_free_outslot(qends, qedge, slot);
+                               timer_tx_off=50;                //rozsviceni diod pri vysilani
+                               CLR_OUT_PIN(LED_PORT,LED1_BIT);
+                               usb_device.ep_events &= ~MASK_EP1TX;
+                       }
+               }
+
+               //if (usb_can_send && )
+
+#ifdef WATCHDOG_ENABLED
+               watchdog_feed();
+#endif /* WATCHDOG_ENABLED */
+
+               /* 10ms timer */
+               if (lt_10msec_expired(10))
+                       timer_10ms();
+       }
+
+       SET_OUT_PIN(LED_PORT,LED_GP);
+       SET_OUT_PIN(LED_PORT,LED_ERR);
+
+       /* unreachable code */
+#ifdef SDCC
+       vec_jmp(0x0);  /* need to call a function from misc to correct linking */
+#endif
+       return 0;
+}
diff --git a/embedded/app/usbcan/setup.c b/embedded/app/usbcan/setup.c
new file mode 100644 (file)
index 0000000..e046c9b
--- /dev/null
@@ -0,0 +1,395 @@
+/* setup.c
+ * Linux CAN-bus device driver.
+ * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
+ * Rewritten for new CAN queues by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.3  17 Jun 2004
+ */
+
+#include "./can/can.h"
+#include "./can/can_sysless.h"
+#include "./can/main.h"
+#include "./can/devcommon.h"
+#include "./can/setup.h"
+//#include "./can/finish.h"
+
+int init_hwspecops(struct candevice_t *candev, int *irqnum_p);
+int init_device_struct(int card, int *chan_param_idx_p, int *irq_param_idx_p);
+int init_chip_struct(struct candevice_t *candev, int chipnr, int irq, long baudrate);
+int init_obj_struct(struct candevice_t *candev, struct canchip_t *hostchip, int objnr);
+
+/**
+ * can_base_addr_fixup - relocates board physical memory addresses to the CPU accessible ones
+ * @candev: pointer to the previously filled device/board, chips and message objects structures
+ * @new_base: @candev new base address
+ *
+ * This function adapts base addresses of all structures of one board
+ * to the new board base address.
+ * It is required for translation between physical and virtual address mappings.
+ * This function is prepared to simplify board specific xxx_request_io() function
+ * for memory mapped devices.
+ */
+int can_base_addr_fixup(struct candevice_t *candev, unsigned long new_base)
+{
+       unsigned long offs;
+       int i, j;
+
+       offs=new_base-candev->dev_base_addr;
+       candev->dev_base_addr=new_base;
+       for(i=0;i<candev->nr_all_chips;i++){
+               candev->chip[i]->chip_base_addr += offs;
+               for(j=0;j<candev->chip[i]->max_objects;j++)
+                       candev->chip[i]->msgobj[j]->obj_base_addr += offs;
+       }
+       return 0;
+}
+
+/**
+ * can_check_dev_taken - checks if bus device description is already taken by driver
+ * @anydev:    pointer to bus specific Linux device description
+ *
+ * Returns: Returns 1 if device is already used by LinCAN driver, 0 otherwise.
+ */
+int can_check_dev_taken(void *anydev)
+{
+       int board_nr;
+       struct candevice_t *candev;
+       void *boarddev;
+
+       for (board_nr=hardware_p->nr_boards; board_nr--; ) {
+               if((candev=hardware_p->candevice[board_nr])==NULL)
+                       continue;
+               boarddev=candev->sysdevptr.anydev;
+               if(boarddev == anydev)
+                       return 1;
+       }
+
+       return 0;
+}
+
+
+/**
+ * register_obj_struct - registers message object into global array
+ * @obj: the initialized message object being registered
+ * @minorbase: wanted minor number, if (-1) automatically selected
+ *
+ * Return Value: returns negative number in the case of fail
+ */
+int register_obj_struct(struct msgobj_t *obj, int minorbase)
+{
+       static int next_minor=0;
+       int i;
+
+       if(minorbase>=0)
+               next_minor=minorbase;
+       if(next_minor>=MAX_TOT_MSGOBJS)
+               next_minor=0;
+       i=next_minor;
+       do{
+               if(objects_p[i]==NULL){
+                       objects_p[i]=obj;
+                       obj->minor=i;
+                       next_minor=i+1;
+                       return 0;
+               }
+               if(++i >= MAX_TOT_MSGOBJS) i=0;
+       }while(i!=next_minor);
+       obj->minor=-1;
+       return -1;
+}
+
+
+/**
+ * register_chip_struct - registers chip into global array
+ * @chip: the initialized chip structure being registered
+ * @minorbase: wanted minor number base, if (-1) automatically selected
+ *
+ * Return Value: returns negative number in the case of fail
+ */
+int register_chip_struct(struct canchip_t *chip, int minorbase)
+{
+       static int next_chip_slot=0;
+       int i;
+
+       if(next_chip_slot>=MAX_TOT_CHIPS)
+               next_chip_slot=0;
+       i=next_chip_slot;
+       do{
+               if(chips_p[i]==NULL){
+                       chips_p[i]=chip;
+
+                       next_chip_slot=i+1;
+                       return 0;
+               }
+               if(++i >= MAX_TOT_CHIPS) i=0;
+       }while(i!=next_chip_slot);
+       return -1;
+}
+
+
+
+/**
+ * init_hw_struct - initializes driver hardware description structures
+ *
+ * The function init_hw_struct() is used to initialize the hardware structure.
+ *
+ * Return Value: returns negative number in the case of fail
+ */
+// int init_hw_struct(void)
+// {
+//     int i=0;
+//     int irq_param_idx=0;
+//     int chan_param_idx=0;
+//
+//     hardware_p->nr_boards=0;
+//     while ( (hw[i] != NULL) & (i < MAX_HW_CARDS) ) {
+//             hardware_p->nr_boards++;
+//
+//             if (init_device_struct(i, &chan_param_idx, &irq_param_idx)) {
+//                     CANMSG("Error initializing candevice_t structures.\n");
+//                     return -ENODEV;
+//             }
+//             i++;
+//     }
+//
+//     return 0;
+// }
+
+/**
+ * init_device_struct - initializes single CAN device/board
+ * @card: index into @hardware_p HW description
+ * @chan_param_idx_p: pointer to the index into arrays of the CAN channel parameters
+ * @irq_param_idx_p: pointer to the index into arrays of the per CAN channel IRQ parameters
+ *
+ * The function builds representation of the one board from parameters provided
+ * in the module parameters arrays:
+ *     @hw[card] .. hardware type,
+ *     @io[card] .. base IO address,
+ *     @baudrate[chan_param_idx] .. per channel baudrate,
+ *     @minor[chan_param_idx] .. optional specification of requested channel minor base,
+ *     @irq[irq_param_idx] .. one or more board/chips IRQ parameters.
+ * The indexes are advanced after consumed parameters if the registration is successful.
+ *
+ * The hardware specific operations of the device/board are initialized by call to
+ * init_hwspecops() function. Then board data are initialized by board specific
+ * init_hw_data() function. Then chips and objects representation is build by
+ * init_chip_struct() function. If all above steps are successful, chips and
+ * message objects are registered into global arrays.
+ *
+ * Return Value: returns negative number in the case of fail
+ */
+// int init_device_struct(int card, int *chan_param_idx_p, int *irq_param_idx_p)
+// {
+//     struct candevice_t *candev;
+//     int ret;
+//     int irqnum;
+//     int chipnr;
+//     long bd;
+//     int irqsig=-1;
+//
+//     candev=(struct candevice_t *)malloc(sizeof(struct candevice_t));
+//     if (candev==NULL)
+//             return -ENOMEM;
+//
+//         memset(candev, 0, sizeof(struct candevice_t));
+//
+//     hardware_p->candevice[card]=candev;
+//     candev->candev_idx=card;
+//
+//     candev=candev;
+//
+//     candev->hwname=hw[card];
+//     candev->io_addr=io[card];
+//     candev->dev_base_addr=io[card];
+//
+//     candev->hwspecops=(struct hwspecops_t *)malloc(sizeof(struct hwspecops_t));
+//     if (candev->hwspecops==NULL)
+//             goto error_nomem;
+//
+//     memset(candev->hwspecops, 0, sizeof(struct hwspecops_t));
+//
+//     if (init_hwspecops(candev, &irqnum))
+//             goto error_nodev;
+//
+//     if (candev->hwspecops->init_hw_data(candev))
+//             goto error_nodev;
+//
+//     /* Alocate and initialize the chip structures */
+//     for (chipnr=0; chipnr < candev->nr_all_chips; chipnr++) {
+//
+//             if(chipnr<irqnum)
+//                     irqsig=irq[*irq_param_idx_p+chipnr];
+//
+//             bd=baudrate[*chan_param_idx_p+chipnr];
+//             if(!bd) bd=baudrate[0];
+//
+//             if ((ret=init_chip_struct(candev, chipnr, irqsig, bd*1000)))
+//                     goto error_chip;
+//     }
+//
+//
+//
+//     for (chipnr=0; chipnr < candev->nr_all_chips; chipnr++) {
+//             int m=minor[*chan_param_idx_p+chipnr];
+//             struct canchip_t *chip=candev->chip[chipnr];
+//             int objnr;
+//
+//             register_chip_struct(chip, m);
+//
+//             for (objnr=0; objnr<chip->max_objects; objnr++) {
+//                     register_obj_struct(chip->msgobj[objnr], m);
+//                     if(m>=0) m++;
+//             }
+//     }
+//
+//     *irq_param_idx_p += irqnum;
+//     *chan_param_idx_p += candev->nr_all_chips;
+//
+//     return 0;
+//
+//     error_nodev:
+//     ret=-ENODEV;
+//     error_chip:
+//     candevice_done(candev);
+//     goto error_both;
+//
+//     error_nomem:
+//     ret=-ENOMEM;
+//
+//     error_both:
+//     hardware_p->candevice[card]=NULL;
+//     free(candev);
+//     return ret;
+//
+// }
+
+/**
+ * init_chip_struct - initializes one CAN chip structure
+ * @candev: pointer to the corresponding CAN device/board
+ * @chipnr: index of the chip in the corresponding device/board structure
+ * @irq: chip IRQ number or (-1) if not appropriate
+ * @baudrate: baudrate in the units of 1Bd
+ *
+ * Chip structure is allocated and chip specific operations are filled by
+ * call to board specific init_chip_data() which calls chip specific
+ * fill_chipspecops(). The message objects are generated by
+ * calls to init_obj_struct() function.
+ *
+ * Return Value: returns negative number in the case of fail
+ */
+int init_chip_struct(struct candevice_t *candev, int chipnr, int irq, long baudrate)
+{
+       struct canchip_t *chip;
+       int objnr;
+       int ret;
+
+       candev->chip[chipnr]=(struct canchip_t *)malloc(sizeof(struct canchip_t));
+       if ((chip=candev->chip[chipnr])==NULL)
+               return -ENOMEM;
+
+        memset(chip, 0, sizeof(struct canchip_t));
+
+       chip->write_register=candev->hwspecops->write_register;
+       chip->read_register=candev->hwspecops->read_register;
+
+       chip->chipspecops=malloc(sizeof(struct chipspecops_t));
+       if (chip->chipspecops==NULL)
+               return -ENOMEM;
+       memset(chip->chipspecops,0,sizeof(struct chipspecops_t));
+
+       chip->chip_idx=chipnr;
+       chip->hostdevice=candev;
+       chip->chip_irq=irq;
+       chip->baudrate=baudrate;
+       chip->flags=0x0;
+
+       if(candev->hwspecops->init_chip_data(candev,chipnr)<0)
+               return -ENODEV;
+
+       for (objnr=0; objnr<chip->max_objects; objnr++) {
+               ret=init_obj_struct(candev, chip, objnr);
+               if(ret<0) return ret;
+       }
+
+       return 0;
+}
+
+
+/**
+ * init_obj_struct - initializes one CAN message object structure
+ * @candev: pointer to the corresponding CAN device/board
+ * @hostchip: pointer to the chip containing this object
+ * @objnr: index of the builded object in the chip structure
+ *
+ * The function initializes message object structure and allocates and initializes
+ * CAN queue chip ends structure.
+ *
+ * Return Value: returns negative number in the case of fail
+ */
+int init_obj_struct(struct candevice_t *candev, struct canchip_t *hostchip, int objnr)
+{
+       struct canque_ends_t *qends;
+       struct msgobj_t *obj;
+       int ret;
+
+       obj=(struct msgobj_t *)malloc(sizeof(struct msgobj_t));
+       hostchip->msgobj[objnr]=obj;
+       if (obj == NULL)
+               return -ENOMEM;
+
+        memset(obj, 0, sizeof(struct msgobj_t));
+       obj->minor=-1;
+
+       atomic_set(&obj->obj_used,0);
+       INIT_LIST_HEAD(&obj->obj_users);
+//     init_timer(&obj->tx_timeout);
+
+       qends = (struct canque_ends_t *)malloc(sizeof(struct canque_ends_t));
+       if(qends == NULL) return -ENOMEM;
+       memset(qends, 0, sizeof(struct canque_ends_t));
+       obj->hostchip=hostchip;
+       obj->object=objnr+1;
+       obj->qends=qends;
+       obj->tx_qedge=NULL;
+       obj->tx_slot=NULL;
+       obj->obj_flags = 0x0;
+
+       ret=canqueue_ends_init_chip(qends, hostchip, obj);
+       if(ret<0) return ret;
+
+       ret=candev->hwspecops->init_obj_data(hostchip,objnr);
+       if(ret<0) return ret;
+
+       return 0;
+}
+
+
+/**
+ * init_hwspecops - finds and initializes board/device specific operations
+ * @candev: pointer to the corresponding CAN device/board
+ * @irqnum_p: optional pointer to the number of interrupts required by board
+ *
+ * The function searches board @hwname in the list of supported boards types.
+ * The board type specific board_register() function is used to initialize
+ * @hwspecops operations.
+ *
+ * Return Value: returns negative number in the case of fail
+ */
+// int init_hwspecops(struct candevice_t *candev, int *irqnum_p)
+// {
+//     const struct boardtype_t *brp;
+//
+//     brp = boardtype_find(candev->hwname);
+//
+//     if(!brp) {
+//             CANMSG("Sorry, hardware \"%s\" is currently not supported.\n",candev->hwname);
+//             return -EINVAL;
+//     }
+//
+//     if(irqnum_p)
+//             *irqnum_p=brp->irqnum;
+//     brp->board_register(candev->hwspecops);
+//
+//     return 0;
+// }
diff --git a/embedded/app/usbcan/sja1000p.c b/embedded/app/usbcan/sja1000p.c
new file mode 100644 (file)
index 0000000..8a527ff
--- /dev/null
@@ -0,0 +1,911 @@
+/* sja1000.c
+ * Linux CAN-bus device driver.
+ * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
+ * Changed for PeliCan mode SJA1000 by Tomasz Motylewski (BFAD GmbH)
+ * T.Motylewski@bfad.de
+ * Rewritten for new CAN queues by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.3  17 Jun 2004
+ */
+
+#include "./can/can.h"
+#include "./can/can_sysdep.h"
+#include "./can/main.h"
+#include "./can/sja1000p.h"
+
+#ifdef CONFIG_OC_LINCAN_DETAILED_ERRORS
+
+static const char *sja1000_ecc_errc_str[]={
+       "bit error",
+       "form error",
+       "stuff error",
+       "other type of error"
+};
+
+static const char *sja1000_ecc_seg_str[]={
+       "?0?",
+       "?1?",
+       "ID.28 to ID.21",
+       "start of frame",
+       "bit SRTR",
+       "bit IDE",
+       "ID.20 to ID.18",
+       "ID.17 to ID.13",
+       "CRC sequence",
+       "reserved bit 0",
+       "data field",
+       "data length code",
+       "bit RTR",
+       "reserved bit 1",
+       "ID.4 to ID.0",
+       "ID.12 to ID.5",
+       "?16?"
+       "active error flag",
+       "intermission",
+       "tolerate dominant bits",
+       "?20?",
+       "?21?",
+       "passive error flag",
+       "error delimiter",
+       "CRC delimiter",
+       "acknowledge slot",
+       "end of frame",
+       "acknowledge delimiter",
+       "overload flag",
+       "?29?",
+       "?30?",
+       "?31?"
+};
+
+#endif /*CONFIG_OC_LINCAN_DETAILED_ERRORS*/
+
+static int sja1000_report_error_limit_counter;
+
+static void sja1000_report_error(struct canchip_t *chip,
+                               unsigned sr, unsigned ir, unsigned ecc)
+{
+       if(sja1000_report_error_limit_counter>=100)
+               return;
+
+       CANMSG("Error: status register: 0x%x irq_register: 0x%02x error: 0x%02x\n",
+               sr, ir, ecc);
+
+       sja1000_report_error_limit_counter+=10;
+
+       if(sja1000_report_error_limit_counter>=100){
+               sja1000_report_error_limit_counter+=10;
+               CANMSG("Error: too many errors, reporting disabled\n");
+               return;
+       }
+
+#ifdef CONFIG_OC_LINCAN_DETAILED_ERRORS
+       CANMSG("SR: BS=%c  ES=%c  TS=%c  RS=%c  TCS=%c TBS=%c DOS=%c RBS=%c\n",
+               sr&sjaSR_BS?'1':'0',sr&sjaSR_ES?'1':'0',
+               sr&sjaSR_TS?'1':'0',sr&sjaSR_RS?'1':'0',
+               sr&sjaSR_TCS?'1':'0',sr&sjaSR_TBS?'1':'0',
+               sr&sjaSR_DOS?'1':'0',sr&sjaSR_RBS?'1':'0');
+       CANMSG("IR: BEI=%c ALI=%c EPI=%c WUI=%c DOI=%c EI=%c  TI=%c  RI=%c\n",
+               sr&sjaIR_BEI?'1':'0',sr&sjaIR_ALI?'1':'0',
+               sr&sjaIR_EPI?'1':'0',sr&sjaIR_WUI?'1':'0',
+               sr&sjaIR_DOI?'1':'0',sr&sjaIR_EI?'1':'0',
+               sr&sjaIR_TI?'1':'0',sr&sjaIR_RI?'1':'0');
+       if((sr&sjaIR_EI) || 1){
+               CANMSG("EI: %s %s %s\n",
+                      sja1000_ecc_errc_str[(ecc&(sjaECC_ERCC1|sjaECC_ERCC0))/sjaECC_ERCC0],
+                      ecc&sjaECC_DIR?"RX":"TX",
+                      sja1000_ecc_seg_str[ecc&sjaECC_SEG_M]
+                     );
+       }
+#endif /*CONFIG_OC_LINCAN_DETAILED_ERRORS*/
+}
+
+
+/**
+ * sja1000p_enable_configuration - enable chip configuration mode
+ * @chip: pointer to chip state structure
+ */
+int sja1000p_enable_configuration(struct canchip_t *chip)
+{
+       int i=0;
+       enum sja1000_PeliCAN_MOD flags;
+
+       can_disable_irq(chip->chip_irq);
+
+       flags=can_read_reg(chip,SJAMOD);
+
+       while ((!(flags & sjaMOD_RM)) && (i<=10)) {
+               can_write_reg(chip, sjaMOD_RM, SJAMOD);
+// TODO: configurable sjaMOD_AFM (32/16 bit acceptance filter)
+// config sjaMOD_LOM (listen only)
+               udelay(100);
+               i++;
+               flags=can_read_reg(chip, SJAMOD);
+       }
+       if (i>=10) {
+               CANMSG("Reset error\n");
+               can_enable_irq(chip->chip_irq);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+/**
+ * sja1000p_disable_configuration - disable chip configuration mode
+ * @chip: pointer to chip state structure
+ */
+int sja1000p_disable_configuration(struct canchip_t *chip)
+{
+       int i=0;
+       enum sja1000_PeliCAN_MOD flags;
+
+       flags=can_read_reg(chip,SJAMOD);
+
+       while ( (flags & sjaMOD_RM) && (i<=50) ) {
+// could be as long as 11*128 bit times after buss-off
+               can_write_reg(chip, 0, SJAMOD);
+// TODO: configurable sjaMOD_AFM (32/16 bit acceptance filter)
+// config sjaMOD_LOM (listen only)
+               udelay(100);
+               i++;
+               flags=can_read_reg(chip, SJAMOD);
+       }
+       if (i>=10) {
+               CANMSG("Error leaving reset status\n");
+               return -ENODEV;
+       }
+
+       can_enable_irq(chip->chip_irq);
+
+       return 0;
+}
+
+/**
+ * sja1000p_chip_config: - can chip configuration
+ * @chip: pointer to chip state structure
+ *
+ * This function configures chip and prepares it for message
+ * transmission and reception. The function resets chip,
+ * resets mask for acceptance of all messages by call to
+ * sja1000p_extended_mask() function and then
+ * computes and sets baudrate with use of function sja1000p_baud_rate().
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
+int sja1000p_chip_config(struct canchip_t *chip)
+{
+       int i;
+       unsigned char n, r;
+
+       if (sja1000p_enable_configuration(chip))
+               return -ENODEV;
+
+       /* Set mode, clock out, comparator */
+       can_write_reg(chip,sjaCDR_PELICAN|chip->sja_cdr_reg,SJACDR);
+
+       /* Ensure, that interrupts are disabled even on the chip level now */
+       can_write_reg(chip, sjaDISABLE_INTERRUPTS, SJAIER);
+
+       /* Set driver output configuration */
+       can_write_reg(chip,chip->sja_ocr_reg,SJAOCR);
+
+       /* Simple check for chip presence */
+       for (i=0, n=0x5a; i<8; i++, n+=0xf) {
+               can_write_reg(chip,n,SJAACR0+i);
+       }
+       for (i=0, n=0x5a; i<8; i++, n+=0xf) {
+               r = n^can_read_reg(chip,SJAACR0+i);
+               if (r) {
+                       CANMSG("sja1000p_chip_config: chip connection broken,"
+                               " readback differ 0x%02x\n", r);
+                       return -ENODEV;
+               }
+       }
+
+
+       if (sja1000p_extended_mask(chip,0x00000000, 0xffffffff))
+               return -ENODEV;
+
+       if (!chip->baudrate)
+               chip->baudrate=1000000;
+       if (sja1000p_baud_rate(chip,chip->baudrate,chip->clock,0,75,0))
+               return -ENODEV;
+
+       /* Enable hardware interrupts */
+       can_write_reg(chip, sjaENABLE_INTERRUPTS, SJAIER);
+
+       sja1000p_disable_configuration(chip);
+
+       return 0;
+}
+
+/**
+ * sja1000p_extended_mask: - setup of extended mask for message filtering
+ * @chip: pointer to chip state structure
+ * @code: can message acceptance code
+ * @mask: can message acceptance mask
+ *
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
+int sja1000p_extended_mask(struct canchip_t *chip, unsigned long code, unsigned  long mask)
+{
+       int i;
+
+       if (sja1000p_enable_configuration(chip))
+               return -ENODEV;
+
+// LSB to +3, MSB to +0
+       for(i=SJA_PeliCAN_AC_LEN; --i>=0;) {
+               can_write_reg(chip,code&0xff,SJAACR0+i);
+               can_write_reg(chip,mask&0xff,SJAAMR0+i);
+               code >>= 8;
+               mask >>= 8;
+       }
+
+       DEBUGMSG("Setting acceptance code to 0x%lx\n",(unsigned long)code);
+       DEBUGMSG("Setting acceptance mask to 0x%lx\n",(unsigned long)mask);
+
+       sja1000p_disable_configuration(chip);
+
+       return 0;
+}
+
+/**
+ * sja1000p_baud_rate: - set communication parameters.
+ * @chip: pointer to chip state structure
+ * @rate: baud rate in Hz
+ * @clock: frequency of sja1000 clock in Hz (ISA osc is 14318000)
+ * @sjw: synchronization jump width (0-3) prescaled clock cycles
+ * @sampl_pt: sample point in % (0-100) sets (TSEG1+1)/(TSEG1+TSEG2+2) ratio
+ * @flags: fields %BTR1_SAM, %OCMODE, %OCPOL, %OCTP, %OCTN, %CLK_OFF, %CBP
+ *
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
+int sja1000p_baud_rate(struct canchip_t *chip, int rate, int clock, int sjw,
+                                                       int sampl_pt, int flags)
+{
+       int best_error = 1000000000, error;
+       int best_tseg=0, best_brp=0, best_rate=0, brp=0;
+       int tseg=0, tseg1=0, tseg2=0;
+
+       if (sja1000p_enable_configuration(chip))
+               return -ENODEV;
+
+       clock /=2;
+
+       /* tseg even = round down, odd = round up */
+       for (tseg=(0+0+2)*2; tseg<=(sjaMAX_TSEG2+sjaMAX_TSEG1+2)*2+1; tseg++) {
+               brp = clock/((1+tseg/2)*rate)+tseg%2;
+               if (brp == 0 || brp > 64)
+                       continue;
+               error = rate - clock/(brp*(1+tseg/2));
+               if (error < 0)
+                       error = -error;
+               if (error <= best_error) {
+                       best_error = error;
+                       best_tseg = tseg/2;
+                       best_brp = brp-1;
+                       best_rate = clock/(brp*(1+tseg/2));
+               }
+       }
+       if (best_error && (rate/best_error < 10)) {
+               CANMSG("baud rate %d is not possible with %d Hz clock\n",
+                                                               rate, 2*clock);
+               CANMSG("%d bps. brp=%d, best_tseg=%d, tseg1=%d, tseg2=%d\n",
+                               best_rate, best_brp, best_tseg, tseg1, tseg2);
+               return -EINVAL;
+       }
+       tseg2 = best_tseg-(sampl_pt*(best_tseg+1))/100;
+       if (tseg2 < 0)
+               tseg2 = 0;
+       if (tseg2 > sjaMAX_TSEG2)
+               tseg2 = sjaMAX_TSEG2;
+       tseg1 = best_tseg-tseg2-2;
+       if (tseg1>sjaMAX_TSEG1) {
+               tseg1 = sjaMAX_TSEG1;
+               tseg2 = best_tseg-tseg1-2;
+       }
+
+       DEBUGMSG("Setting %d bps.\n", best_rate);
+       DEBUGMSG("brp=%d, best_tseg=%d, tseg1=%d, tseg2=%d, sampl_pt=%d\n",
+                                       best_brp, best_tseg, tseg1, tseg2,
+                                       (100*(best_tseg-tseg2)/(best_tseg+1)));
+
+
+       can_write_reg(chip, sjw<<6 | best_brp, SJABTR0);
+       can_write_reg(chip, ((flags & BTR1_SAM) != 0)<<7 | (tseg2<<4)
+                                       | tseg1, SJABTR1);
+
+       sja1000p_disable_configuration(chip);
+
+       return 0;
+}
+
+/**
+ * sja1000p_read: - reads and distributes one or more received messages
+ * @chip: pointer to chip state structure
+ * @obj: pinter to CAN message queue information
+ *
+ * File: src/sja1000p.c
+ */
+void sja1000p_read(struct canchip_t *chip, struct msgobj_t *obj) {
+       int i, flags, len, datastart;
+       do {
+               flags = can_read_reg(chip,SJAFRM);
+               if(flags&sjaFRM_FF) {
+                       obj->rx_msg.id =
+                               (can_read_reg(chip,SJAID0)<<21) +
+                               (can_read_reg(chip,SJAID1)<<13) +
+                               (can_read_reg(chip,SJAID2)<<5) +
+                               (can_read_reg(chip,SJAID3)>>3);
+                       datastart = SJADATE;
+               } else {
+                       obj->rx_msg.id =
+                               (can_read_reg(chip,SJAID0)<<3) +
+                               (can_read_reg(chip,SJAID1)>>5);
+                       datastart = SJADATS;
+               }
+               obj->rx_msg.flags =
+                       ((flags & sjaFRM_RTR) ? MSG_RTR : 0) |
+                       ((flags & sjaFRM_FF) ? MSG_EXT : 0);
+               len = flags & sjaFRM_DLC_M;
+               obj->rx_msg.length = len;
+               if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH;
+               for(i=0; i< len; i++) {
+                       obj->rx_msg.data[i]=can_read_reg(chip,datastart+i);
+               }
+
+               /* fill CAN message timestamp */
+               can_filltimestamp(&obj->rx_msg.timestamp);
+
+               canque_filter_msg2edges(obj->qends, &obj->rx_msg);
+
+               can_write_reg(chip, sjaCMR_RRB, SJACMR);
+
+       } while (can_read_reg(chip, SJASR) & sjaSR_RBS);
+}
+
+/**
+ * sja1000p_pre_read_config: - prepares message object for message reception
+ * @chip: pointer to chip state structure
+ * @obj: pointer to message object state structure
+ *
+ * Return Value: negative value reports error.
+ *     Positive value indicates immediate reception of message.
+ * File: src/sja1000p.c
+ */
+int sja1000p_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj)
+{
+       int status;
+       status=can_read_reg(chip,SJASR);
+
+       if(status  & sjaSR_BS) {
+               /* Try to recover from error condition */
+               DEBUGMSG("sja1000p_pre_read_config bus-off recover 0x%x\n",status);
+               sja1000p_enable_configuration(chip);
+               can_write_reg(chip, 0, SJARXERR);
+               can_write_reg(chip, 0, SJATXERR1);
+               can_read_reg(chip, SJAECC);
+               sja1000p_disable_configuration(chip);
+       }
+
+       if (!(status&sjaSR_RBS)) {
+               return 0;
+       }
+
+       can_write_reg(chip, sjaDISABLE_INTERRUPTS, SJAIER); //disable interrupts for a moment
+       sja1000p_read(chip, obj);
+       can_write_reg(chip, sjaENABLE_INTERRUPTS, SJAIER); //enable interrupts
+       return 1;
+}
+
+#define MAX_TRANSMIT_WAIT_LOOPS 10
+/**
+ * sja1000p_pre_write_config: - prepares message object for message transmission
+ * @chip: pointer to chip state structure
+ * @obj: pointer to message object state structure
+ * @msg: pointer to CAN message
+ *
+ * This function prepares selected message object for future initiation
+ * of message transmission by sja1000p_send_msg() function.
+ * The CAN message data and message ID are transfered from @msg slot
+ * into chip buffer in this function.
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
+int sja1000p_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj,
+                                                       struct canmsg_t *msg)
+{
+       int i=0;
+       unsigned int id;
+       int status;
+       int len;
+
+       /* Wait until Transmit Buffer Status is released */
+       while ( !((status=can_read_reg(chip, SJASR)) & sjaSR_TBS) &&
+                                               i++<MAX_TRANSMIT_WAIT_LOOPS) {
+               udelay(i);
+       }
+
+       if(status & sjaSR_BS) {
+               /* Try to recover from error condition */
+               DEBUGMSG("sja1000p_pre_write_config bus-off recover 0x%x\n",status);
+               sja1000p_enable_configuration(chip);
+               can_write_reg(chip, 0, SJARXERR);
+               can_write_reg(chip, 0, SJATXERR1);
+               can_read_reg(chip, SJAECC);
+               sja1000p_disable_configuration(chip);
+       }
+       if (!(can_read_reg(chip, SJASR) & sjaSR_TBS)) {
+               CANMSG("Transmit timed out, cancelling\n");
+// here we should check if there is no write/select waiting for this
+// transmit. If so, set error ret and wake up.
+// CHECKME: if we do not disable sjaIER_TIE (TX IRQ) here we get interrupt
+// immediately
+               can_write_reg(chip, sjaCMR_AT, SJACMR);
+               i=0;
+               while ( !(can_read_reg(chip, SJASR) & sjaSR_TBS) &&
+                                               i++<MAX_TRANSMIT_WAIT_LOOPS) {
+                       udelay(i);
+               }
+               if (!(can_read_reg(chip, SJASR) & sjaSR_TBS)) {
+                       CANMSG("Could not cancel, please reset\n");
+                       return -EIO;
+               }
+       }
+       len = msg->length;
+       if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH;
+       /* len &= sjaFRM_DLC_M; ensured by above condition already */
+       can_write_reg(chip, ((msg->flags&MSG_EXT)?sjaFRM_FF:0) |
+               ((msg->flags & MSG_RTR) ? sjaFRM_RTR : 0) | len, SJAFRM);
+       if(msg->flags&MSG_EXT) {
+               id=msg->id<<3;
+               can_write_reg(chip, id & 0xff, SJAID3);
+               id >>= 8;
+               can_write_reg(chip, id & 0xff, SJAID2);
+               id >>= 8;
+               can_write_reg(chip, id & 0xff, SJAID1);
+               id >>= 8;
+               can_write_reg(chip, id, SJAID0);
+               for(i=0; i < len; i++) {
+                       can_write_reg(chip, msg->data[i], SJADATE+i);
+               }
+       } else {
+               id=msg->id<<5;
+               can_write_reg(chip, (id >> 8) & 0xff, SJAID0);
+               can_write_reg(chip, id & 0xff, SJAID1);
+               for(i=0; i < len; i++) {
+                       can_write_reg(chip, msg->data[i], SJADATS+i);
+               }
+       }
+       return 0;
+}
+
+/**
+ * sja1000p_send_msg: - initiate message transmission
+ * @chip: pointer to chip state structure
+ * @obj: pointer to message object state structure
+ * @msg: pointer to CAN message
+ *
+ * This function is called after sja1000p_pre_write_config() function,
+ * which prepares data in chip buffer.
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
+int sja1000p_send_msg(struct canchip_t *chip, struct msgobj_t *obj,
+                                                       struct canmsg_t *msg)
+{
+       can_write_reg(chip, sjaCMR_TR, SJACMR);
+
+       return 0;
+}
+
+/**
+ * sja1000p_check_tx_stat: - checks state of transmission engine
+ * @chip: pointer to chip state structure
+ *
+ * Return Value: negative value reports error.
+ *     Positive return value indicates transmission under way status.
+ *     Zero value indicates finishing of all issued transmission requests.
+ * File: src/sja1000p.c
+ */
+int sja1000p_check_tx_stat(struct canchip_t *chip)
+{
+       if (can_read_reg(chip,SJASR) & sjaSR_TCS)
+               return 0;
+       else
+               return 1;
+}
+
+/**
+ * sja1000p_set_btregs: -  configures bitrate registers
+ * @chip: pointer to chip state structure
+ * @btr0: bitrate register 0
+ * @btr1: bitrate register 1
+ *
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
+int sja1000p_set_btregs(struct canchip_t *chip, unsigned short btr0,
+                                                       unsigned short btr1)
+{
+       if (sja1000p_enable_configuration(chip))
+               return -ENODEV;
+
+       can_write_reg(chip, btr0, SJABTR0);
+       can_write_reg(chip, btr1, SJABTR1);
+
+       sja1000p_disable_configuration(chip);
+
+       return 0;
+}
+
+/**
+ * sja1000p_start_chip: -  starts chip message processing
+ * @chip: pointer to chip state structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
+int sja1000p_start_chip(struct canchip_t *chip)
+{
+       enum sja1000_PeliCAN_MOD flags;
+
+       flags = can_read_reg(chip, SJAMOD) & (sjaMOD_LOM|sjaMOD_STM|sjaMOD_AFM|sjaMOD_SM);
+       can_write_reg(chip, flags, SJAMOD);
+
+       sja1000_report_error_limit_counter=0;
+
+       return 0;
+}
+
+/**
+ * sja1000p_stop_chip: -  stops chip message processing
+ * @chip: pointer to chip state structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
+int sja1000p_stop_chip(struct canchip_t *chip)
+{
+       enum sja1000_PeliCAN_MOD flags;
+
+       flags = can_read_reg(chip, SJAMOD) & (sjaMOD_LOM|sjaMOD_STM|sjaMOD_AFM|sjaMOD_SM);
+       can_write_reg(chip, flags|sjaMOD_RM, SJAMOD);
+
+       return 0;
+}
+
+/**
+ * sja1000p_attach_to_chip: - attaches to the chip, setups registers and state
+ * @chip: pointer to chip state structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
+int sja1000p_attach_to_chip(struct canchip_t *chip)
+{
+       return 0;
+}
+
+/**
+ * sja1000p_release_chip: - called before chip structure removal if %CHIP_ATTACHED is set
+ * @chip: pointer to chip state structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
+int sja1000p_release_chip(struct canchip_t *chip)
+{
+       sja1000p_stop_chip(chip);
+       can_write_reg(chip, sjaDISABLE_INTERRUPTS, SJAIER);
+
+       return 0;
+}
+
+/**
+ * sja1000p_remote_request: - configures message object and asks for RTR message
+ * @chip: pointer to chip state structure
+ * @obj: pointer to message object structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
+int sja1000p_remote_request(struct canchip_t *chip, struct msgobj_t *obj)
+{
+       CANMSG("sja1000p_remote_request not implemented\n");
+       return -ENOSYS;
+}
+
+/**
+ * sja1000p_standard_mask: - setup of mask for message filtering
+ * @chip: pointer to chip state structure
+ * @code: can message acceptance code
+ * @mask: can message acceptance mask
+ *
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
+int sja1000p_standard_mask(struct canchip_t *chip, unsigned short code,
+               unsigned short mask)
+{
+       CANMSG("sja1000p_standard_mask not implemented\n");
+       return -ENOSYS;
+}
+
+/**
+ * sja1000p_clear_objects: - clears state of all message object residing in chip
+ * @chip: pointer to chip state structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
+int sja1000p_clear_objects(struct canchip_t *chip)
+{
+       CANMSG("sja1000p_clear_objects not implemented\n");
+       return -ENOSYS;
+}
+
+/**
+ * sja1000p_config_irqs: - tunes chip hardware interrupt delivery
+ * @chip: pointer to chip state structure
+ * @irqs: requested chip IRQ configuration
+ *
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
+int sja1000p_config_irqs(struct canchip_t *chip, short irqs)
+{
+       CANMSG("sja1000p_config_irqs not implemented\n");
+       return -ENOSYS;
+}
+
+/**
+ * sja1000p_irq_write_handler: - part of ISR code responsible for transmit events
+ * @chip: pointer to chip state structure
+ * @obj: pointer to attached queue description
+ *
+ * The main purpose of this function is to read message from attached queues
+ * and transfer message contents into CAN controller chip.
+ * This subroutine is called by
+ * sja1000p_irq_write_handler() for transmit events.
+ * File: src/sja1000p.c
+ */
+void sja1000p_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj)
+{
+       int cmd;
+
+       if(obj->tx_slot){
+               /* Do local transmitted message distribution if enabled */
+               if (processlocal){
+                       /* fill CAN message timestamp */
+                       can_filltimestamp(&obj->tx_slot->msg.timestamp);
+
+                       obj->tx_slot->msg.flags |= MSG_LOCAL;
+                       canque_filter_msg2edges(obj->qends, &obj->tx_slot->msg);
+               }
+               /* Free transmitted slot */
+               canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+               obj->tx_slot=NULL;
+       }
+
+       can_msgobj_clear_fl(obj,TX_PENDING);
+       cmd=canque_test_outslot(obj->qends, &obj->tx_qedge, &obj->tx_slot);
+       if(cmd<0)
+               return;
+       can_msgobj_set_fl(obj,TX_PENDING);
+
+       if (chip->chipspecops->pre_write_config(chip, obj, &obj->tx_slot->msg)) {
+               obj->ret = -1;
+               canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_PREP);
+               canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+               obj->tx_slot=NULL;
+               return;
+       }
+       if (chip->chipspecops->send_msg(chip, obj, &obj->tx_slot->msg)) {
+               obj->ret = -1;
+               canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_SEND);
+               canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+               obj->tx_slot=NULL;
+               return;
+       }
+
+}
+
+#define MAX_RETR 10
+
+/**
+ * sja1000p_irq_handler: - interrupt service routine
+ * @irq: interrupt vector number, this value is system specific
+ * @chip: pointer to chip state structure
+ *
+ * Interrupt handler is activated when state of CAN controller chip changes,
+ * there is message to be read or there is more space for new messages or
+ * error occurs. The receive events results in reading of the message from
+ * CAN controller chip and distribution of message through attached
+ * message queues.
+ * File: src/sja1000p.c
+ */
+int sja1000p_irq_handler(int irq, struct canchip_t *chip)
+{
+       int irq_register, status, error_code;
+       struct msgobj_t *obj=chip->msgobj[0];
+       int loop_cnt=CHIP_MAX_IRQLOOP;
+
+       irq_register=can_read_reg(chip,SJAIR);
+//     DEBUGMSG("sja1000_irq_handler: SJAIR:%02x\n",irq_register);
+//     DEBUGMSG("sja1000_irq_handler: SJASR:%02x\n",
+//                                     can_read_reg(chip,SJASR));
+
+       if ((irq_register & (sjaIR_BEI|sjaIR_EPI|sjaIR_DOI|sjaIR_EI|sjaIR_TI|sjaIR_RI)) == 0)
+               return CANCHIP_IRQ_NONE;
+
+       if(!(chip->flags&CHIP_CONFIGURED)) {
+               CANMSG("sja1000p_irq_handler: called for non-configured device, irq_register 0x%02x\n", irq_register);
+               return CANCHIP_IRQ_NONE;
+       }
+
+       status=can_read_reg(chip,SJASR);
+
+       do {
+
+               if(!loop_cnt--) {
+                       CANMSG("sja1000p_irq_handler IRQ %d stuck\n",irq);
+                       return CANCHIP_IRQ_STUCK;
+               }
+
+               /* (irq_register & sjaIR_RI) */
+               /*      old variant using SJAIR, collides with intended use with irq_accept */
+               if (status & sjaSR_RBS) {
+                       DEBUGMSG("sja1000_irq_handler: RI or RBS\n");
+                       sja1000p_read(chip,obj);
+                       obj->ret = 0;
+               }
+
+               /* (irq_register & sjaIR_TI) */
+               /*      old variant using SJAIR, collides with intended use with irq_accept */
+               if (((status & sjaSR_TBS) && can_msgobj_test_fl(obj,TX_PENDING))||
+                   (can_msgobj_test_fl(obj,TX_REQUEST))) {
+                       DEBUGMSG("sja1000_irq_handler: TI or TX_PENDING and TBS\n");
+                       obj->ret = 0;
+                       can_msgobj_set_fl(obj,TX_REQUEST);
+                       while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
+                               can_msgobj_clear_fl(obj,TX_REQUEST);
+
+                               if (can_read_reg(chip, SJASR) & sjaSR_TBS)
+                                       sja1000p_irq_write_handler(chip, obj);
+
+                               can_msgobj_clear_fl(obj,TX_LOCK);
+                               if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
+                               DEBUGMSG("TX looping in sja1000_irq_handler\n");
+                       }
+               }
+               if ((irq_register & (sjaIR_EI|sjaIR_BEI|sjaIR_EPI|sjaIR_DOI)) != 0) {
+                       // Some error happened
+                       error_code=can_read_reg(chip,SJAECC);
+                       sja1000_report_error(chip, status, irq_register, error_code);
+// FIXME: chip should be brought to usable state. Transmission cancelled if in progress.
+// Reset flag set to 0 if chip is already off the bus. Full state report
+                       obj->ret=-1;
+
+                       if(error_code == 0xd9) {
+                               obj->ret= -ENXIO;
+                               /* no such device or address - no ACK received */
+                       }
+                       if(obj->tx_retry_cnt++>MAX_RETR) {
+                               can_write_reg(chip, sjaCMR_AT, SJACMR); // cancel any transmition
+                               obj->tx_retry_cnt = 0;
+                       }
+                       if(status&sjaSR_BS) {
+                               CANMSG("bus-off, resetting sja1000p\n");
+                               can_write_reg(chip, 0, SJAMOD);
+                       }
+
+                       if(obj->tx_slot){
+                               canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_BUS);
+                               /*canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+                               obj->tx_slot=NULL;*/
+                       }
+
+               } else {
+                       if(sja1000_report_error_limit_counter)
+                               sja1000_report_error_limit_counter--;
+                       obj->tx_retry_cnt=0;
+               }
+
+               irq_register=can_read_reg(chip,SJAIR);
+
+               status=can_read_reg(chip,SJASR);
+
+               if(((status & sjaSR_TBS) && can_msgobj_test_fl(obj,TX_PENDING)) ||
+                  (irq_register & sjaIR_TI))
+                        can_msgobj_set_fl(obj,TX_REQUEST);
+
+       } while((irq_register & (sjaIR_BEI|sjaIR_EPI|sjaIR_DOI|sjaIR_EI|sjaIR_RI)) ||
+               (can_msgobj_test_fl(obj,TX_REQUEST) && !can_msgobj_test_fl(obj,TX_LOCK)) ||
+               (status & sjaSR_RBS));
+
+       return CANCHIP_IRQ_HANDLED;
+}
+
+/**
+ * sja1000p_wakeup_tx: - wakeups TX processing
+ * @chip: pointer to chip state structure
+ * @obj: pointer to message object structure
+ *
+ * Function is responsible for initiating message transmition.
+ * It is responsible for clearing of object TX_REQUEST flag
+ *
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
+int sja1000p_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj)
+{
+
+       can_preempt_disable();
+
+       can_msgobj_set_fl(obj,TX_PENDING);
+       can_msgobj_set_fl(obj,TX_REQUEST);
+       while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
+               can_msgobj_clear_fl(obj,TX_REQUEST);
+
+               if (can_read_reg(chip, SJASR) & sjaSR_TBS){
+                       obj->tx_retry_cnt=0;
+                       sja1000p_irq_write_handler(chip, obj);
+               }
+
+               can_msgobj_clear_fl(obj,TX_LOCK);
+               if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
+               DEBUGMSG("TX looping in sja1000p_wakeup_tx\n");
+       }
+
+       can_preempt_enable();
+       return 0;
+}
+
+int sja1000p_register(struct chipspecops_t *chipspecops)
+{
+       CANMSG("initializing sja1000p chip operations\n");
+       chipspecops->chip_config=sja1000p_chip_config;
+       chipspecops->baud_rate=sja1000p_baud_rate;
+       chipspecops->standard_mask=sja1000p_standard_mask;
+       chipspecops->extended_mask=sja1000p_extended_mask;
+       chipspecops->message15_mask=sja1000p_extended_mask;
+       chipspecops->clear_objects=sja1000p_clear_objects;
+       chipspecops->config_irqs=sja1000p_config_irqs;
+       chipspecops->pre_read_config=sja1000p_pre_read_config;
+       chipspecops->pre_write_config=sja1000p_pre_write_config;
+       chipspecops->send_msg=sja1000p_send_msg;
+       chipspecops->check_tx_stat=sja1000p_check_tx_stat;
+       chipspecops->wakeup_tx=sja1000p_wakeup_tx;
+       chipspecops->remote_request=sja1000p_remote_request;
+       chipspecops->enable_configuration=sja1000p_enable_configuration;
+       chipspecops->disable_configuration=sja1000p_disable_configuration;
+       chipspecops->attach_to_chip=sja1000p_attach_to_chip;
+       chipspecops->release_chip=sja1000p_release_chip;
+       chipspecops->set_btregs=sja1000p_set_btregs;
+       chipspecops->start_chip=sja1000p_start_chip;
+       chipspecops->stop_chip=sja1000p_stop_chip;
+       chipspecops->irq_handler=sja1000p_irq_handler;
+       chipspecops->irq_accept=NULL;
+       return 0;
+}
+
+/**
+ * sja1000p_fill_chipspecops - fills chip specific operations
+ * @chip: pointer to chip representation structure
+ *
+ * The function fills chip specific operations for sja1000 (PeliCAN) chip.
+ *
+ * Return Value: returns negative number in the case of fail
+ */
+int sja1000p_fill_chipspecops(struct canchip_t *chip)
+{
+       chip->chip_type="sja1000p";
+       chip->max_objects=1;
+       sja1000p_register(chip->chipspecops);
+       return 0;
+}
diff --git a/embedded/app/usbcan/ul_usb1.c b/embedded/app/usbcan/ul_usb1.c
new file mode 100644 (file)
index 0000000..abb1626
--- /dev/null
@@ -0,0 +1,539 @@
+/* ul_usb1.c
+ * Linux CAN-bus device driver.
+ * Written by Jan Kriz email:johen@post.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.3  17 Jun 2004
+ *
+ * Based on
+ *     USB Skeleton driver - 2.2
+ *
+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
+ *
+ *     This program 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, version 2.
+ *
+ * This driver is based on the 2.6.3 version of drivers/usb/usb-skeleton.c
+ * but has been rewritten to be easier to read and use.
+ *
+ */
+
+#include "./can/can.h"
+#include "./can/can_sysdep.h"
+#include "./can/main.h"
+#include "./can/devcommon.h"
+#include "./can/setup.h"
+// #include "./can/finish.h"
+#include "./can/i82527.h"
+//#include "../include/sja1000.h"
+#include "./can/sja1000p.h"
+
+#include "./can/errno.h"
+
+#include "./can/ul_usb1.h"
+
+/* Get a minor range for your devices from the usb maintainer */
+#define USB_SKEL_MINOR_BASE    192
+
+#define CAN_OP_MASK 0x80
+#define CAN_OP_READ 0x80
+#define CAN_OP_WRITE 0x00
+
+
+       /* our private defines. if this grows any larger, use your own .h file */
+#define MAX_TRANSFER           (PAGE_SIZE - 512)
+/* MAX_TRANSFER is chosen so that the VM is not stressed by
+   allocations > PAGE_SIZE and the number of packets in a page
+   is an integer 512 is the largest possible packet on EHCI */
+#define WRITES_IN_FLIGHT       8
+/* arbitrarily chosen */
+
+/* Define these values to match your devices */
+#define USB_SKEL_VENDOR_ID     0xDEAD
+#define USB_SKEL_PRODUCT_ID    0x1001
+
+/* table of devices that work with this driver */
+// static struct usb_device_id ul_usb1_table [] = {
+//     { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
+//     { }                                     /* Terminating entry */
+// };
+// MODULE_DEVICE_TABLE(usb, ul_usb1_table);
+
+// extern struct file_operations can_fops;
+
+// struct ul_usb1_combo {
+//     struct usb_ul_usb1 * dev;
+//     struct urb * urb;
+// };
+
+/*
+ * IO_RANGE is the io-memory range that gets reserved, please adjust according
+ * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
+ * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
+ */
+#define IO_RANGE 0x100
+
+/** ul_usb1_request_io
+ * ul_usb1_request_io: - reserve io or memory range for can board
+ * @candev: pointer to candevice/board which asks for io. Field @io_addr
+ *     of @candev is used in most cases to define start of the range
+ *
+ * The function ul_usb1_request_io() is used to reserve the io-memory. If your
+ * hardware uses a dedicated memory range as hardware control registers you
+ * will have to add the code to reserve this memory as well.
+ * %IO_RANGE is the io-memory range that gets reserved, please adjust according
+ * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
+ * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
+ * Return Value: The function returns zero on success or %-ENODEV on failure
+ * File: src/ul_usb1.c
+ */
+int ul_usb1_request_io(struct candevice_t *candev)
+{
+//     ((struct usb_ul_usb1*)candev->sysdevptr.anydev)->candev=candev;
+       return 0;
+}
+
+/** ul_usb1_release_io
+ * ul_usb1_release_io - free reserved io memory range
+ * @candev: pointer to candevice/board which releases io
+ *
+ * The function ul_usb1_release_io() is used to free reserved io-memory.
+ * In case you have reserved more io memory, don't forget to free it here.
+ * IO_RANGE is the io-memory range that gets released, please adjust according
+ * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
+ * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
+ * Return Value: The function always returns zero
+ * File: src/ul_usb1.c
+ */
+int ul_usb1_release_io(struct candevice_t *candev)
+{
+/*     struct usb_ul_usb1 *dev;
+       if (candev->sysdevptr.anydev){
+               dev=(struct usb_ul_usb1*) candev->sysdevptr.anydev;
+               usb_put_dev(dev->udev);
+               usb_kill_urb(dev->irq);
+               usb_free_urb(dev->irq);
+               kfree(dev->bulk_in_buffer);
+               kfree(dev->int_in_buffer);
+               if (dev->candev){
+                       dev->candev->sysdevptr.anydev=NULL;
+                       //cleanup_usbdev(dev->candev);
+               }
+               kfree(dev);
+       }*/
+       return 0;
+}
+
+/** ul_usb1_reset
+ * ul_usb1_reset - hardware reset routine
+ * @candev: Pointer to candevice/board structure
+ *
+ * The function ul_usb1_reset() is used to give a hardware reset. This is
+ * rather hardware specific so I haven't included example code. Don't forget to
+ * check the reset status of the chip before returning.
+ * Return Value: The function returns zero on success or %-ENODEV on failure
+ * File: src/ul_usb1.c
+ */
+int ul_usb1_reset(struct candevice_t *candev)
+{
+       return 0;
+}
+
+#define RESET_ADDR 0x0
+#define NR_82527 0
+#define NR_SJA1000 1
+
+/** ul_usb1_init_hw_data
+ * ul_usb1_init_hw_data - Initialize hardware cards
+ * @candev: Pointer to candevice/board structure
+ *
+ * The function ul_usb1_init_hw_data() is used to initialize the hardware
+ * structure containing information about the installed CAN-board.
+ * %RESET_ADDR represents the io-address of the hardware reset register.
+ * %NR_82527 represents the number of Intel 82527 chips on the board.
+ * %NR_SJA1000 represents the number of Philips sja1000 chips on the board.
+ * The flags entry can currently only be %CANDEV_PROGRAMMABLE_IRQ to indicate that
+ * the hardware uses programmable interrupts.
+ * Return Value: The function always returns zero
+ * File: src/ul_usb1.c
+ */
+int ul_usb1_init_hw_data(struct candevice_t *candev)
+{
+       candev->res_addr=RESET_ADDR;
+       candev->nr_82527_chips=NR_82527;
+       candev->nr_sja1000_chips=NR_SJA1000;
+       candev->nr_all_chips=NR_82527+NR_SJA1000;
+       candev->flags |= CANDEV_PROGRAMMABLE_IRQ*0;
+
+       return 0;
+}
+
+/** ul_usb1_init_chip_data
+ * ul_usb1_init_chip_data - Initialize chips
+ * @candev: Pointer to candevice/board structure
+ * @chipnr: Number of the CAN chip on the hardware card
+ *
+ * The function ul_usb1_init_chip_data() is used to initialize the hardware
+ * structure containing information about the CAN chips.
+ * %CHIP_TYPE represents the type of CAN chip. %CHIP_TYPE can be "i82527" or
+ * "sja1000".
+ * The @chip_base_addr entry represents the start of the 'official' memory map
+ * of the installed chip. It's likely that this is the same as the @io_addr
+ * argument supplied at module loading time.
+ * The @clock entry holds the chip clock value in Hz.
+ * The entry @sja_cdr_reg holds hardware specific options for the Clock Divider
+ * register. Options defined in the %sja1000.h file:
+ * %sjaCDR_CLKOUT_MASK, %sjaCDR_CLK_OFF, %sjaCDR_RXINPEN, %sjaCDR_CBP, %sjaCDR_PELICAN
+ * The entry @sja_ocr_reg holds hardware specific options for the Output Control
+ * register. Options defined in the %sja1000.h file:
+ * %sjaOCR_MODE_BIPHASE, %sjaOCR_MODE_TEST, %sjaOCR_MODE_NORMAL, %sjaOCR_MODE_CLOCK,
+ * %sjaOCR_TX0_LH, %sjaOCR_TX1_ZZ.
+ * The entry @int_clk_reg holds hardware specific options for the Clock Out
+ * register. Options defined in the %i82527.h file:
+ * %iCLK_CD0, %iCLK_CD1, %iCLK_CD2, %iCLK_CD3, %iCLK_SL0, %iCLK_SL1.
+ * The entry @int_bus_reg holds hardware specific options for the Bus
+ * Configuration register. Options defined in the %i82527.h file:
+ * %iBUS_DR0, %iBUS_DR1, %iBUS_DT1, %iBUS_POL, %iBUS_CBY.
+ * The entry @int_cpu_reg holds hardware specific options for the cpu interface
+ * register. Options defined in the %i82527.h file:
+ * %iCPU_CEN, %iCPU_MUX, %iCPU_SLP, %iCPU_PWD, %iCPU_DMC, %iCPU_DSC, %iCPU_RST.
+ * Return Value: The function always returns zero
+ * File: src/ul_usb1.c
+ */
+int ul_usb1_init_chip_data(struct candevice_t *candev, int chipnr)
+{
+       /*i82527_fill_chipspecops(candev->chip[chipnr]);*/
+       /*sja1000_fill_chipspecops(candev->chip[chipnr]);*/
+       sja1000p_fill_chipspecops(candev->chip[chipnr]);
+
+       candev->chip[chipnr]->flags|= CHIP_IRQ_CUSTOM;
+
+       candev->chip[chipnr]->chip_base_addr=0;
+       candev->chip[chipnr]->clock = 24000000;
+       candev->chip[chipnr]->int_cpu_reg = iCPU_DSC;
+       candev->chip[chipnr]->int_clk_reg = iCLK_SL1;
+       candev->chip[chipnr]->int_bus_reg = iBUS_CBY;
+       candev->chip[chipnr]->sja_cdr_reg = sjaCDR_CBP | sjaCDR_CLK_OFF;
+       candev->chip[chipnr]->sja_ocr_reg = sjaOCR_MODE_NORMAL |
+                                                               sjaOCR_TX0_LH;
+
+       candev->chip[chipnr]->chip_data=(void *)malloc(sizeof(struct ul_usb1_chip_data));
+       if (candev->chip[chipnr]->chip_data==NULL)
+               return -ENOMEM;
+       return 0;
+}
+
+/** ul_usb1_init_obj_data
+ * ul_usb1_init_obj_data - Initialize message buffers
+ * @chip: Pointer to chip specific structure
+ * @objnr: Number of the message buffer
+ *
+ * The function ul_usb1_init_obj_data() is used to initialize the hardware
+ * structure containing information about the different message objects on the
+ * CAN chip. In case of the sja1000 there's only one message object but on the
+ * i82527 chip there are 15.
+ * The code below is for a i82527 chip and initializes the object base addresses
+ * The entry @obj_base_addr represents the first memory address of the message
+ * object. In case of the sja1000 @obj_base_addr is taken the same as the chips
+ * base address.
+ * Unless the hardware uses a segmented memory map, flags can be set zero.
+ * Return Value: The function always returns zero
+ * File: src/ul_usb1.c
+ */
+int ul_usb1_init_obj_data(struct canchip_t *chip, int objnr)
+{
+       chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr+(objnr+1)*0x10;
+
+       return 0;
+}
+
+/** ul_usb1_program_irq
+ * ul_usb1_program_irq - program interrupts
+ * @candev: Pointer to candevice/board structure
+ *
+ * The function ul_usb1_program_irq() is used for hardware that uses
+ * programmable interrupts. If your hardware doesn't use programmable interrupts
+ * you should not set the @candevices_t->flags entry to %CANDEV_PROGRAMMABLE_IRQ and
+ * leave this function unedited. Again this function is hardware specific so
+ * there's no example code.
+ * Return value: The function returns zero on success or %-ENODEV on failure
+ * File: src/ul_usb1.c
+ */
+int ul_usb1_program_irq(struct candevice_t *candev)
+{
+       return 0;
+}
+
+/** ul_usb1_write_register
+ * ul_usb1_write_register - Low level write register routine
+ * @data: data to be written
+ * @address: memory address to write to
+ *
+ * The function ul_usb1_write_register() is used to write to hardware registers
+ * on the CAN chip. You should only have to edit this function if your hardware
+ * uses some specific write process.
+ * Return Value: The function does not return a value
+ * File: src/ul_usb1.c
+ */
+void ul_usb1_write_register(unsigned data, unsigned long address)
+{
+       can_write((uint8_t)(address & 0xFF), (uint8_t *)&data);
+}
+
+/** ul_usb1_read_register
+ * ul_usb1_read_register - Low level read register routine
+ * @address: memory address to read from
+ *
+ * The function ul_usb1_read_register() is used to read from hardware registers
+ * on the CAN chip. You should only have to edit this function if your hardware
+ * uses some specific read process.
+ * Return Value: The function returns the value stored in @address
+ * File: src/ul_usb1.c
+ */
+unsigned ul_usb1_read_register(unsigned long address)
+{
+       uint8_t data;
+       can_read((uint8_t)(address & 0xFF), (uint8_t *)&data);
+       return data;
+}
+
+/* !!! Don't change this function !!! */
+int ul_usb1_register(struct hwspecops_t *hwspecops)
+{
+       hwspecops->request_io = ul_usb1_request_io;
+       hwspecops->release_io = ul_usb1_release_io;
+       hwspecops->reset = ul_usb1_reset;
+       hwspecops->init_hw_data = ul_usb1_init_hw_data;
+       hwspecops->init_chip_data = ul_usb1_init_chip_data;
+       hwspecops->init_obj_data = ul_usb1_init_obj_data;
+       hwspecops->write_register = ul_usb1_write_register;
+       hwspecops->read_register = ul_usb1_read_register;
+       hwspecops->program_irq = ul_usb1_program_irq;
+       return 0;
+}
+
+
+
+
+/* --------------------------------------------------------------------------------------------------- */
+
+
+// static void ul_usb1_irq(struct urb *urb)
+// {
+//     struct usb_ul_usb1 *dev = urb->context;
+//     struct ul_usb1_combo devc;
+//     int retval;
+//
+//     CANMSG("Interrupt poll\n");
+//
+//     switch (urb->status) {
+//     case 0:
+//             /* success */
+//             break;
+//     case -ECONNRESET:
+//     case -ENOENT:
+//     case -ESHUTDOWN:
+//             /* this urb is terminated, clean up */
+//             CANMSG("%s - urb shutting down with status: %d\n", __FUNCTION__, urb->status);
+//             return;
+//     default:
+//             CANMSG("%s - nonzero urb status received: %d\n", __FUNCTION__, urb->status);
+//             goto exit;
+//     }
+//
+//     devc.dev = dev;
+//     devc.urb = urb;
+//
+//     dev->candev->chip[0]->chipspecops->irq_handler(0,dev->candev->chip[0]);
+//     CANMSG("Interrupt caught\n");
+//
+//  exit:
+//     retval = usb_submit_urb (urb, GFP_ATOMIC);
+//     if (retval)
+//             CANMSG("%s - usb_submit_urb failed with result %d\n",
+//                  __FUNCTION__, retval);
+// }
+
+// static void ul_usb1_delete(struct usb_ul_usb1 *dev)
+// {
+//     usb_put_dev(dev->udev);
+//     usb_kill_urb(dev->irq);
+//     usb_free_urb(dev->irq);
+//     kfree(dev->bulk_in_buffer);
+//     kfree(dev->int_in_buffer);
+//     if (dev->candev){
+//             dev->candev->sysdevptr.anydev=NULL;
+//             cleanup_usbdev(dev->candev);
+//     }
+//     kfree(dev);
+// }
+
+// static int ul_usb1_probe(struct usb_interface *interface, const struct usb_device_id *id)
+// {
+//     struct usb_ul_usb1 *dev;
+//     struct usb_host_interface *iface_desc;
+//     struct usb_endpoint_descriptor *endpoint;
+//     struct candevice_t *candev;
+//     size_t buffer_size;
+//     int i;
+//     int retval = -ENOMEM;
+//
+//     /* allocate memory for our device state and initialize it */
+//     dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+//     if (!dev) {
+//             err("Out of memory");
+//             goto error;
+//     }
+//     sema_init(&dev->limit_sem, WRITES_IN_FLIGHT);
+//     mutex_init(&dev->io_mutex);
+//     spin_lock_init(&dev->err_lock);
+//     init_usb_anchor(&dev->submitted);
+//
+// //  dev->udev = usb_get_dev(interface_to_usbdev(interface));
+//     dev->udev = interface_to_usbdev(interface);
+//     dev->interface = interface;
+//
+//     /* set up the endpoint information */
+//     /* use only the first bulk-in and bulk-out endpoints */
+//     iface_desc = interface->cur_altsetting;
+//     for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+//             endpoint = &iface_desc->endpoint[i].desc;
+//
+//             if (!dev->bulk_in_endpointAddr &&
+//                 usb_endpoint_is_bulk_in(endpoint)) {
+//                     /* we found a bulk in endpoint */
+//                     buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+//                     dev->bulk_in_size = buffer_size;
+//                     dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
+//                     dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
+//                     if (!dev->bulk_in_buffer) {
+//                             err("Could not allocate bulk_in_buffer");
+//                             goto error;
+//                     }
+//             }
+//
+//             if (!dev->bulk_out_endpointAddr &&
+//                 usb_endpoint_is_bulk_out(endpoint)) {
+//                     /* we found a bulk out endpoint */
+//                             dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
+//             }
+//
+//             if (!dev->int_in_endpointAddr &&
+//                 usb_endpoint_is_int_in(endpoint)) {
+//                     /* we found an interrupt in endpoint */
+//                     buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+//                     dev->int_in_size = buffer_size;
+//                     dev->int_in_endpointAddr = endpoint->bEndpointAddress;
+//                     dev->int_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
+//                     dev->int_in_interval = endpoint->bInterval;
+//                     if (!dev->int_in_buffer) {
+//                             err("Could not allocate int_in_buffer");
+//                             goto error;
+//                     }
+//             }
+//     }
+//     if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr && dev->int_in_endpointAddr)) {
+//             err("Could not find all bulk-in, bulk-out and interrupt endpoints");
+//             goto error;
+//     }
+//
+//     /* save our data pointer in this interface device */
+//     usb_set_intfdata(interface, dev);
+//
+//     if (main_init_done==1)
+//             register_usbdev("ul_usb1",(void *) dev);
+//     else {
+//             mutex_lock(&usbdev_reg_mutex);
+//             if (main_init_done==1)
+//                     register_usbdev("ul_usb1",(void *) dev);
+//             else {
+//                     for (i=0;i<MAX_HW_CARDS;i++){
+//                             if (usbregq[i]==NULL){
+//                                     usbregq[i]=(struct usbdev_reg_query *)can_checked_malloc(sizeof(struct usbdev_reg_query));
+//                                     if (!usbregq[i]){
+//                                             CANMSG("Error allocating usbdev_reg_query");
+//                                             mutex_unlock(&usbdev_reg_mutex);
+//                                             goto error;
+//                                     }
+//                                     sprintf (usbregq[i]->hwname,"ul_usb1");
+//                                     usbregq[i]->anydev=(void *) dev;
+//                                     break;
+//                             }
+//                     }
+//                     if (i==MAX_HW_CARDS){
+//                             CANMSG("No free space to register new card");
+//                             mutex_unlock(&usbdev_reg_mutex);
+//                             goto error;
+//                     }
+//             }
+//             mutex_unlock(&usbdev_reg_mutex);
+//     }
+//
+//     dev->irq = usb_alloc_urb(0, GFP_KERNEL);
+//     if (!dev->irq){
+//             CANMSG("Error allocating usb urb\n");
+//             goto error;
+//     }
+//     dev->irq->dev = dev->udev;
+//     usb_fill_int_urb(dev->irq, dev->udev,
+//                      usb_rcvintpipe(dev->udev, dev->int_in_endpointAddr),
+//                      dev->int_in_buffer, dev->int_in_size,
+//                      ul_usb1_irq, dev, dev->int_in_interval);
+// /*  usb_fill_bulk_urb(dev->irq, dev->udev,
+//                      usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
+//                      dev->int_in_buffer, dev->int_in_size,
+//                      ul_usb1_irq, dev);*/
+//
+// /*  dev->irq->transfer_dma = wacom->data_dma;
+//     dev->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;*/
+//     retval=usb_submit_urb(dev->irq, GFP_KERNEL);
+//     if (retval){
+//             CANMSG("INT URB %d\n",retval);
+//             return -EIO;
+//     }else
+//             CANMSG("INT URB SUCCCESS\n");
+//
+//     /* let the user know what node this device is now attached to */
+//     info("USB Skeleton device now attached");
+//     return 0;
+//
+// error:
+//             ul_usb1_delete(dev);
+//     return retval;
+// }
+
+// static void ul_usb1_disconnect(struct usb_interface *interface)
+// {
+//     struct usb_ul_usb1 *dev;
+//     int minor = interface->minor;
+//
+//     dev = usb_get_intfdata(interface);
+//     usb_set_intfdata(interface, NULL);
+//
+//     /* prevent more I/O from starting */
+//     mutex_lock(&dev->io_mutex);
+//     dev->interface = NULL;
+//     mutex_unlock(&dev->io_mutex);
+//
+//     //usb_kill_anchored_urbs(&dev->submitted);
+//
+//     ul_usb1_delete(dev);
+//
+//     info("USB Skeleton now disconnected");
+// }
+
+// static struct usb_driver ul_usb1_driver = {
+//     .name =         "ul_usb1-can",
+//     .id_table = ul_usb1_table,
+//     .probe =        ul_usb1_probe,
+//     .disconnect =   ul_usb1_disconnect,
+//     .id_table =     ul_usb1_table,
+// };
+
+// int ul_usb1_init(void){
+//     return usb_register(&ul_usb1_driver);
+// }
+//
+// void ul_usb1_exit(void){
+//     usb_deregister(&ul_usb1_driver);
+// }
diff --git a/embedded/app/usbcan/usb/usb_defs.h b/embedded/app/usbcan/usb/usb_defs.h
new file mode 100644 (file)
index 0000000..48dde4e
--- /dev/null
@@ -0,0 +1,452 @@
+
+#ifndef USB_DEFS_MODULE
+  #define USB_DEFS_MODULE
+
+  #include <usb/usb_spec.h>
+//  #include <usb/pdiusb.h>
+  #include <usb/lpcusb.h>
+  #include <endian.h>
+  #include <cpu_def.h>
+
+  #include <endian.h>
+  #if __BYTE_ORDER == __BIG_ENDIAN
+    #include <byteswap.h>
+    #define SWAP(x) ((((x) & 0xFF) << 8) | (((x) >> 8) & 0xFF))
+  #else /*__LITTLE_ENDIAN*/
+    #define SWAP(x) (x)
+  #endif
+
+  #ifndef CODE
+    #define CODE
+  #endif
+
+       #ifdef USB_MAX_PACKET
+               #undef USB_MAX_PACKET
+               #define USB_MAX_PACKET 16
+       #endif
+/*****************************************************/
+/*** Static data structures for device descriptors ***/
+/*****************************************************/
+#ifndef USB_VENDOR_ID
+  #define USB_VENDOR_ID      0x1669  /* vymyslene cislo ( snad ho nikdo nema ... ;-) */
+#endif
+#ifndef USB_PRODUCT_ID
+  #define USB_PRODUCT_ID     0x1011  /* test code for ULAD21 */
+#endif
+  #define USB_RELEASE_VER    0x0010
+
+/*** Class codes for device description ***/
+  #define USB_CLASS_CODE      0xFF
+  #define USB_SUBCLASS_CODE   0x00
+  #define USB_PROTOCOL_CODE   0x00
+
+
+  #define NUM_ENDPOINTS  2
+  #define CONFIG_DESCRIPTOR_LENGTH sizeof( USB_CONFIGURATION_DESCRIPTOR) \
+                                     + sizeof( USB_INTERFACE_DESCRIPTOR) \
+                                     + ( NUM_ENDPOINTS * sizeof( USB_ENDPOINT_DESCRIPTOR))
+
+/*** Device descriptor ***/
+  CODE const USB_DEVICE_DESCRIPTOR DeviceDescription = {
+    sizeof( USB_DEVICE_DESCRIPTOR),
+    USB_DESCRIPTOR_TYPE_DEVICE,
+    SWAP( 0x0100),
+    USB_CLASS_CODE,
+    USB_SUBCLASS_CODE,
+    USB_PROTOCOL_CODE,
+    USB_MAX_PACKET0,
+    SWAP( USB_VENDOR_ID),
+    SWAP( USB_PRODUCT_ID),
+    SWAP( USB_RELEASE_VER),
+    1, /* manufacturer string ID */
+    2, /* product string ID */
+    3, /* serial number string ID */
+    1
+  };
+
+/*** All In Configuration 0 ***/
+  CODE const struct {
+    USB_CONFIGURATION_DESCRIPTOR configuration;
+    USB_INTERFACE_DESCRIPTOR interface;
+    USB_ENDPOINT_DESCRIPTOR endpoint_tx;
+    USB_ENDPOINT_DESCRIPTOR endpoint_rx;
+  } ConfigDescription = {
+    /*** Configuration descriptor ***/
+    {
+      sizeof( USB_CONFIGURATION_DESCRIPTOR),
+      USB_DESCRIPTOR_TYPE_CONFIGURATION,
+      SWAP( CONFIG_DESCRIPTOR_LENGTH),
+      1, /* cnt of interfaces */
+      1, /* this configuration ID */
+      4, /* config.name string ID*/
+      0x80, /* cfg, in spec is, taha bit 7 must be set to one -> 0xe0 , orig 0x60*/
+      0x32    /* device power current from host 100mA */
+    },
+    /*** Interface Descriptor ***/
+    {
+      sizeof( USB_INTERFACE_DESCRIPTOR),
+      USB_DESCRIPTOR_TYPE_INTERFACE,
+      0,    /* index of this interface for SetInterface request */
+      0,    /* ID alternate interface */
+      NUM_ENDPOINTS,
+      USB_CLASS_CODE,
+      USB_SUBCLASS_CODE,
+      USB_PROTOCOL_CODE,
+      5
+    },
+    /*** Endpoint 1 - Tx,Bulk ***/
+    {
+      sizeof( USB_ENDPOINT_DESCRIPTOR),
+      USB_DESCRIPTOR_TYPE_ENDPOINT,
+      0x01,
+      USB_ENDPOINT_TYPE_BULK,
+      SWAP( USB_MAX_PACKET),
+      0
+    },
+    /*** Endpoint 1 - Rx,Bulk ***/
+    {
+      sizeof( USB_ENDPOINT_DESCRIPTOR),
+      USB_DESCRIPTOR_TYPE_ENDPOINT,
+      0x81,
+      USB_ENDPOINT_TYPE_BULK,
+      SWAP( USB_MAX_PACKET),
+      0
+    }
+  };
+  /*** Strings - in unicode ***/
+  CODE const char Str0Desc[] = {  /* supported languages of strings */
+    4, 0x03,  /* 2+2*N , N is count of supported languages */
+    0x09,0x04 /* english 0x0409 */
+  };
+
+  CODE const char Str1Desc[] = {  /* 1 = manufacturer */
+    48,0x03,
+    'S',0,
+    'm',0,
+    'o',0,
+    'l',0,
+    'i',0,
+    'k',0,
+    ',',0,
+    'B',0,
+    'a',0,
+    'r',0,
+    't',0,
+    'o',0,
+    's',0,
+    'i',0,
+    'n',0,
+    's',0,
+    'k',0,
+    'i',0,
+    ',',0,
+    'P',0,
+    'i',0,
+    's',0,
+    'a',0
+  };
+
+  CODE const char Str2Desc[] = {  /* 2 = product */
+    38, 0x03,
+    'u',0,
+    'L',0,
+    'a',0,
+    'n',0,
+    '2',0,
+    'u',0,
+    's',0,
+    'b',0,
+    ' ',0,
+    'c',0,
+    'o',0,
+    'n',0,
+    'v',0,
+    'e',0,
+    'r',0,
+    't',0,
+    'o',0,
+    'r',0
+  };
+
+
+  CODE const char Str3Desc[] = {  /* 3 = version */
+    26, 0x03,
+    '2',0,
+    '3',0,
+    '.',0,
+    '0',0,
+    '7',0,
+    '.',0,
+    '0',0,
+    '4',0,
+    '-',0,
+    '1',0,
+    '.',0,
+    '1',0
+  };
+  CODE const char Str4Desc[] = {  /* 4 = configuration */
+    34, 0x03,
+    'C',0,
+    'o',0,
+    'n',0,
+    'f',0,
+    'i',0,
+    'g',0,
+    'u',0,
+    'r',0,
+    'a',0,
+    't',0,
+    'i',0,
+    'o',0,
+    'n',0,
+    ' ',0,
+    '#',0,
+    '1',0
+  };
+  CODE const char Str5Desc[] = {  /* 5 = interface */
+    26,0x03,
+    'I',0,
+    'n',0,
+    't',0,
+    'e',0,
+    'r',0,
+    'f',0,
+    'a',0,
+    'c',0,
+    'e',0,
+    ' ',0,
+    '#',0,
+    '0',0
+  };
+
+  CODE const char Str6Desc[] = {  /* EP1 OUT descriptor */
+    136,0x03,
+    'E',0,
+    'P',0,
+    '1',0,
+    'O',0,
+    'U',0,
+    'T',0,
+    '-',0,
+    's',0,
+    'e',0,
+    'n',0,
+    'd',0,
+    ' ',0,
+    'm',0,
+    'e',0,
+    's',0,
+    's',0,
+    'a',0,
+    'g',0,
+    'e',0,
+    '-',0,
+    'd',0,
+    'a',0,
+    'd',0,
+    'r',0,
+    ',',0,
+    's',0,
+    'a',0,
+    'd',0,
+    'r',0,
+    ',',0,
+    'c',0,
+    'm',0,
+    'd',0,
+    ',',0,
+    'f',0,
+    'l',0,
+    'g',0,
+    ',',0,
+    's',0,
+    't',0,
+    'a',0,
+    'm',0,
+    'p',0,
+    ',',0,
+    'f',0,
+    'r',0,
+    'e',0,
+    'e',0,
+    ',',0,
+    'l',0,
+    'e',0,
+    'n',0,
+    '-',0,
+    'l',0,
+    'o',0,
+    ',',0,
+    'l',0,
+    'e',0,
+    'n',0,
+    '-',0,
+    'h',0,
+    'i',0,
+    ',',0,
+    'd',0,
+    'a',0,
+    't',0,
+    'a',0
+  };
+
+  CODE const char Str7Desc[] = {  /* EP2 IN descriptor */
+    140,0x03,
+    'E',0,
+    'P',0,
+    '1',0,
+    'I',0,
+    'N',0,
+    '-',0,
+    'r',0,
+    'e',0,
+    'c',0,
+    'e',0,
+    'i',0,
+    'v',0,
+    'e',0,
+    ' ',0,
+    'm',0,
+    'e',0,
+    's',0,
+    's',0,
+    'a',0,
+    'g',0,
+    'e',0,
+    '-',0,
+    'd',0,
+    'a',0,
+    'd',0,
+    'r',0,
+    ',',0,
+    's',0,
+    'a',0,
+    'd',0,
+    'r',0,
+    ',',0,
+    'c',0,
+    'm',0,
+    'd',0,
+    ',',0,
+    'f',0,
+    'l',0,
+    'g',0,
+    ',',0,
+    's',0,
+    't',0,
+    'a',0,
+    'm',0,
+    'p',0,
+    ',',0,
+    'f',0,
+    'r',0,
+    'e',0,
+    'e',0,
+    ',',0,
+    'l',0,
+    'e',0,
+    'n',0,
+    '-',0,
+    'l',0,
+    'o',0,
+    ',',0,
+    'l',0,
+    'e',0,
+    'n',0,
+    '-',0,
+    'h',0,
+    'i',0,
+    ',',0,
+    'd',0,
+    'a',0,
+    't',0,
+    'a',0
+  };
+
+  CODE const char Str8Desc[] = {  /* EP1 OUT descriptor */
+    136,0x03,
+    'E',0,
+    'P',0,
+    '2',0,
+    'O',0,
+    'U',0,
+    'T',0,
+    '-',0,
+    's',0,
+    'e',0,
+    'n',0,
+    'd',0,
+    ' ',0,
+    'm',0,
+    'e',0,
+    's',0,
+    's',0,
+    'a',0,
+    'g',0,
+    'e',0,
+    '-',0,
+    'd',0,
+    'a',0,
+    'd',0,
+    'r',0,
+    ',',0,
+    's',0,
+    'a',0,
+    'd',0,
+    'r',0,
+    ',',0,
+    'c',0,
+    'm',0,
+    'd',0,
+    ',',0,
+    'f',0,
+    'l',0,
+    'g',0,
+    ',',0,
+    's',0,
+    't',0,
+    'a',0,
+    'm',0,
+    'p',0,
+    ',',0,
+    'f',0,
+    'r',0,
+    'e',0,
+    'e',0,
+    ',',0,
+    'l',0,
+    'e',0,
+    'n',0,
+    '-',0,
+    'l',0,
+    'o',0,
+    ',',0,
+    'l',0,
+    'e',0,
+    'n',0,
+    '-',0,
+    'h',0,
+    'i',0,
+    ',',0,
+    'd',0,
+    'a',0,
+    't',0,
+    'a',0
+  };
+
+  #define CNT_STRINGS 0x09
+
+  /* all strings in pointers array */
+  CODE const PUSB_STRING_DESCRIPTOR StringDescriptors[] = {
+    (PUSB_STRING_DESCRIPTOR) Str0Desc,
+    (PUSB_STRING_DESCRIPTOR) Str1Desc,
+    (PUSB_STRING_DESCRIPTOR) Str2Desc,
+    (PUSB_STRING_DESCRIPTOR) Str3Desc,
+    (PUSB_STRING_DESCRIPTOR) Str4Desc,
+    (PUSB_STRING_DESCRIPTOR) Str5Desc,
+    (PUSB_STRING_DESCRIPTOR) Str6Desc,
+    (PUSB_STRING_DESCRIPTOR) Str7Desc,
+    (PUSB_STRING_DESCRIPTOR) Str8Desc
+  };
+
+#endif /* USB_DEFS_MODULE */
diff --git a/embedded/app/usbcan/usb/usb_vend.h b/embedded/app/usbcan/usb/usb_vend.h
new file mode 100644 (file)
index 0000000..30835d0
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef USBCAN_VENDOR
+#define USBCAN_VENDOR
+
+#include <usb/usb.h>
+
+#define USBCAN_VENDOR_BAUD_RATE_SET    (1)
+#define USBCAN_VENDOR_BAUD_RATE_STATUS (2)
+#define USBCAN_VENDOR_SET_BTREGS       (3)
+#define USBCAN_VENDOR_CHECK_TX_STAT    (4)
+#define USBCAN_VENDOR_START_CHIP       (5)
+#define USBCAN_VENDOR_STOP_CHIP        (6)
+#define USBCAN_VENDOR_EXT_MASK_SET     (7)
+#define USBCAN_VENDOR_EXT_MASK_STATUS  (8)
+
+int usbcan_vendor(usb_device_t *udev);
+
+int set_ext_mask_complete_fnc(struct usb_ep_t *ep, int status);
+
+#endif /* USBCAN_VENDOR */
diff --git a/embedded/app/usbcan/usb_srq.c b/embedded/app/usbcan/usb_srq.c
new file mode 100644 (file)
index 0000000..4299a83
--- /dev/null
@@ -0,0 +1,238 @@
+/*****************************************************/
+/***   Module : USB module                         ***/
+/***   Author : Roman Bartosinski (C) 28.04.2002   ***/
+/***   Modify : 08.08.2002, 16.04.2003             ***/
+/*****************************************************/
+
+#include <string.h>
+#include <cpu_def.h>
+#include <system_def.h>
+#include <usb/usb.h>
+#include <usb/usb_spec.h>
+#include <usb/usbdebug.h>
+#include <usb/usb_srq.h>
+#include <usb/usb_defs.h>
+#include <usb/lpcusb.h>
+
+//extern ul_dcnv_state_t ep1_dcnv_state;
+
+  // ****************************
+  int usb_stdreq_get_status( usb_device_t *udev)
+  {
+    unsigned char c,buf[2] = { 0, 0};
+    unsigned char epid = (unsigned char) udev->request.wIndex;
+    usb_ep_t *ep0 = &(udev->ep0);
+
+    usb_debug_print( DEBUG_LEVEL_HIGH, ("GetStatus\n"));
+    switch( udev->request.bmRequestType & USB_RECIPIENT) {
+      case USB_RECIPIENT_DEVICE:
+        if ( udev->flags & USB_FLAG_REMOTE_WAKE) //.remote_wake_up == 1)
+          buf[0] = USB_GETSTATUS_REMOTE_WAKEUP_ENABLED | USB_GETSTATUS_SELF_POWERED;
+        else
+          buf[0] = USB_GETSTATUS_SELF_POWERED;
+        break;
+      case USB_RECIPIENT_INTERFACE:
+        break;
+      case USB_RECIPIENT_ENDPOINT:
+/*        if ( epid & USB_ENDPOINT_DIRECTION_MASK)
+          c = pdiSelectEp(pdiEp2Idx(epid)); // endpoint in
+        else
+          c = pdiSelectEp(pdiEp2Idx(epid));     // endpoint Out
+          #ifdef PDIUSBD12
+          buf[0] = (( c & PDI_SELEP_STALL) == PDI_SELEP_STALL);
+          #else
+          buf[0] = 0;
+          #endif*/
+        break;
+      default:
+        return USB_COMPLETE_FAIL;
+    }
+    usb_udev_write_endpoint( ep0, buf, 2);
+    return USB_COMPLETE_OK;
+  }
+
+  int usb_stdreq_clear_feature( usb_device_t *udev)
+  {
+    USB_DEVICE_REQUEST *dreq = &(udev->request);
+    unsigned char epid = (unsigned char) dreq->wIndex;
+
+    usb_debug_print( DEBUG_LEVEL_HIGH, ("ClearFeature\n"));
+    switch( dreq->bmRequestType & USB_RECIPIENT) {
+      case USB_RECIPIENT_DEVICE:
+        if ( dreq->wValue == USB_FEATURE_REMOTE_WAKEUP) {
+          udev->flags &= ~USB_FLAG_REMOTE_WAKE; //.remote_wake_up = 0;
+          usb_udev_ack_setup( udev);
+          return USB_COMPLETE_OK;
+        }
+        break;
+      case USB_RECIPIENT_ENDPOINT:
+        if ( dreq->wValue == USB_FEATURE_ENDPOINT_STALL) {
+          lpc_usb_clrstallEP(epid);
+          usb_udev_ack_setup( udev);
+         //initialize state of ulan convertor
+         switch (epid&(USB_ENDPOINT_DIRECTION_MASK|0x03)) {
+           case 0x01:                          //rx USB -> tx ulan
+//           ul_freemsg(ep1_dcnv_state.tx_fd);
+//              ep1_dcnv_state.tx_2send=-1;
+             break;
+           case 0x81:                          //tx USB -> rx ulan
+//           ul_freemsg(ep1_dcnv_state.rx_fd);
+//              ep1_dcnv_state.rx_2rec=-1;
+//              ep1_dcnv_state.rx_wait4host=0;
+             break;
+         }
+          return USB_COMPLETE_OK;
+        }
+        break;
+    }
+    return USB_COMPLETE_FAIL;
+  }
+
+  int usb_stdreq_set_feature( usb_device_t *udev)
+  {
+    USB_DEVICE_REQUEST *dreq = &(udev->request);
+    unsigned char epid = (unsigned char) dreq->wIndex;
+
+    usb_debug_print( DEBUG_LEVEL_HIGH, ("SetFeature\n"));
+    switch( dreq->bmRequestType & USB_RECIPIENT) {
+      case USB_RECIPIENT_DEVICE:
+        if ( dreq->wValue == USB_FEATURE_REMOTE_WAKEUP) {
+          udev->flags |= USB_FLAG_REMOTE_WAKE; //.remote_wake_up = 1;
+          lpc_usb_setstallEP (epid);
+          usb_udev_ack_setup( udev);
+          return USB_COMPLETE_OK;
+        }
+        break;
+      case USB_RECIPIENT_ENDPOINT:
+        if ( dreq->wValue == USB_FEATURE_ENDPOINT_STALL) {
+          usb_udev_ack_setup( udev);
+          return USB_COMPLETE_OK;
+        }
+        break;
+    }
+    return USB_COMPLETE_FAIL;
+  }
+
+  int usb_stdreq_set_address( usb_device_t *udev)
+  {
+    int adr;
+    USB_DEVICE_REQUEST *dreq = &(udev->request);
+    adr=dreq->wValue & DEVICE_ADDRESS_MASK;
+    usb_debug_print( DEBUG_LEVEL_HIGH, ("SetAddr-%d\n",adr));
+    usb_udev_ack_setup( udev);
+    lpc_usb_set_addr(adr);
+    return USB_COMPLETE_OK;
+  }
+
+  int usb_stdreq_get_configuration( usb_device_t *udev)
+  {
+    unsigned char buf = udev->configuration; //usb_flags.configured;
+    usb_ep_t *ep0 = &(udev->ep0);
+    usb_debug_print( DEBUG_LEVEL_HIGH, ("GetConfig\n"));
+    usb_udev_write_endpoint( ep0, &buf, 1);
+    return USB_COMPLETE_OK;
+  }
+
+  int usb_stdreq_set_configuration( usb_device_t *udev)
+  {
+    USB_DEVICE_REQUEST *dreq = &(udev->request);
+    unsigned char iCfg = dreq->wValue & 0xff;
+    usb_debug_print( DEBUG_LEVEL_HIGH, ("SetConfig\n"));
+    if ( iCfg < 2) {       // put device in unconfigured state or set configuration 1 ( no else)
+      usb_udev_ack_setup( udev);
+      lpc_usb_config_device(iCfg);
+      if ( iCfg) {
+        udev->flags |= USB_FLAG_CONFIGURED;
+        lpc_usb_configEP(0x01,USB_MAX_PACKET0);
+        lpc_usb_configEP(0x81,USB_MAX_PACKET0);
+      } else {
+        udev->flags &= ~USB_FLAG_CONFIGURED;
+      }
+      udev->configuration = iCfg;  //usb_flags.configured = iCfg;
+      return USB_COMPLETE_OK;
+    } else
+      return USB_COMPLETE_FAIL;
+  }
+
+  int usb_stdreq_get_interface( usb_device_t *udev)
+  {
+    unsigned char buf = 0; /// udev->interface
+    usb_ep_t *ep0 = &(udev->ep0);
+    usb_debug_print( DEBUG_LEVEL_HIGH, ("GetIface\n"));
+    usb_udev_write_endpoint( ep0, &buf, 1);
+    return USB_COMPLETE_OK;
+  }
+
+  int usb_stdreq_set_interface( usb_device_t *udev)
+  {
+    USB_DEVICE_REQUEST *dreq = &(udev->request);
+
+    usb_debug_print( DEBUG_LEVEL_HIGH, ("SetIface\n"));
+    if (( dreq->wValue == 0) && ( dreq->wIndex == 0)) {
+      usb_udev_ack_setup( udev);
+      return USB_COMPLETE_OK;
+    } else {
+      return USB_COMPLETE_FAIL;
+    }
+  }
+
+  int usb_stdreq_get_descriptor( usb_device_t *udev)
+  {
+    unsigned char *pDesc;
+    unsigned short Len = 0;
+    USB_DEVICE_REQUEST *dreq = &(udev->request);
+    int i;
+
+    i = (dreq->wValue >> 8) & 0xff; /* MSB part of wValue */
+    usb_debug_print( DEBUG_LEVEL_HIGH, ("GetDesc\n"));
+    usb_debug_print( DEBUG_LEVEL_VERBOSE, ( " - %s desc.\n", /*(unsigned int)*/ usb_debug_get_std_descriptor(i)));
+
+    switch (i) {
+      case USB_DESCRIPTOR_TYPE_DEVICE:
+        pDesc = (unsigned char *)&DeviceDescription;
+        Len = sizeof( USB_DEVICE_DESCRIPTOR);
+        break;
+      case USB_DESCRIPTOR_TYPE_CONFIGURATION:
+        pDesc = (unsigned char *)&ConfigDescription;
+        Len = CONFIG_DESCRIPTOR_LENGTH;
+        break;
+      case USB_DESCRIPTOR_TYPE_INTERFACE:
+        pDesc = (unsigned char *)&ConfigDescription.interface;
+        Len = sizeof( USB_INTERFACE_DESCRIPTOR);
+        break;
+      case USB_DESCRIPTOR_TYPE_STRING:
+        i = dreq->wValue & 0xff; /* LSB part of wValue */
+        /*printf("Get descriptor indx=0x%02x\n", i);*/
+        if ( i < CNT_STRINGS) {
+          pDesc = (unsigned char *) StringDescriptors[ i];
+          Len = *pDesc;
+          /*usb_debug_print(0,("indx=0x%02x ptr=%p len=%d : '%c'\n", i, pDesc, Len, pDesc[2]));*/
+        } else {
+          return USB_COMPLETE_FAIL;
+        }
+        break;
+      default:
+        return USB_COMPLETE_FAIL;
+    }
+    if ( dreq->wLength < Len) Len = dreq->wLength;
+    usb_send_control_data( udev, pDesc, Len);
+    return USB_COMPLETE_OK;
+  }
+
+
+/*
+  void usb_init_stdreq_fnc( usb_device_t *udev)
+  {
+    // memset( udev->stdreq, 0, sizeof(udev->stdreq));
+
+    udev->stdreq[USB_REQUEST_GET_STATUS] = usb_stdreq_get_status;
+    udev->stdreq[USB_REQUEST_CLEAR_FEATURE] = usb_stdreq_clear_feature;
+    udev->stdreq[USB_REQUEST_SET_FEATURE] = usb_stdreq_set_feature;
+    udev->stdreq[USB_REQUEST_SET_ADDRESS] = usb_stdreq_set_address;
+    udev->stdreq[USB_REQUEST_GET_DESCRIPTOR] = usb_stdreq_get_descriptor;
+    udev->stdreq[USB_REQUEST_GET_CONFIGURATION] = usb_stdreq_get_configuration;
+    udev->stdreq[USB_REQUEST_SET_CONFIGURATION] = usb_stdreq_set_configuration;
+    udev->stdreq[USB_REQUEST_GET_INTERFACE] = usb_stdreq_get_interface;
+    udev->stdreq[USB_REQUEST_SET_INTERFACE] = usb_stdreq_set_interface;
+  }
+*/
diff --git a/embedded/app/usbcan/usb_vend.c b/embedded/app/usbcan/usb_vend.c
new file mode 100644 (file)
index 0000000..29cd74b
--- /dev/null
@@ -0,0 +1,181 @@
+// #define CAN_DEBUG
+
+#include <stdio.h>
+#include <system_def.h>
+#include <hal_intr.h>
+#include "./can/can.h"
+#include "./can/can_sysless.h"
+#include "./can/main.h"
+#include "./can/devcommon.h"
+#include "./usb/usb_vend.h"
+#include "./can/ul_usb1.h"
+#include <endian.h>
+#if __BYTE_ORDER == __BIG_ENDIAN
+  #include <byteswap.h>
+#endif
+
+extern struct canuser_t *canuser;
+extern uint8_t vendor_ret;
+
+int set_ext_mask_complete_fnc(struct usb_ep_t *ep, int status){
+  int dest_chip;
+
+       unsigned long code;
+       unsigned long mask;
+
+       struct ul_usb1_chip_data *chip_data=NULL;
+
+       usb_device_t *udev=ep->udev;
+       unsigned char *data=ep->ptr - ep->actual;
+
+       if (udev->request.bRequest==USBCAN_VENDOR_EXT_MASK_SET){
+               dest_chip=(udev->request.wIndex);
+               if ((dest_chip>=MAX_TOT_CHIPS)||(dest_chip<0))
+                       goto error;
+               if (!chips_p[dest_chip])
+                       goto error;
+               if ((chip_data=((struct ul_usb1_chip_data*)(chips_p[dest_chip]->chip_data)))==NULL)
+                       goto nodata;
+
+               mask=*(uint32_t *)(data);
+               code=*(uint32_t *)(data+4);
+               #if __BYTE_ORDER == __BIG_ENDIAN
+               mask  = bswap_32( mask);
+               code  = bswap_32( code);
+               #endif
+
+
+               if (chips_p[dest_chip]->chipspecops->extended_mask(chips_p[dest_chip], code, mask)<0)
+                       goto error;
+               chip_data->flags |= UL_USB1_CHIP_MASK_SET;
+       }
+       return 0;
+error:
+       chip_data->flags &= ~UL_USB1_CHIP_MASK_SET;
+nodata:
+       return -1;
+}
+
+int set_baud_rate_complete_fnc(struct usb_ep_t *ep, int status){
+  int dest_chip;
+
+       int32_t rate,sjw,sampl_pt,flags;
+
+       struct ul_usb1_chip_data *chip_data=NULL;
+
+       usb_device_t *udev=ep->udev;
+       unsigned char *data=ep->ptr - ep->actual;
+
+       if (udev->request.bRequest==USBCAN_VENDOR_BAUD_RATE_SET){
+               dest_chip=(udev->request.wIndex);
+               if ((dest_chip>=MAX_TOT_CHIPS)||(dest_chip<0))
+                       goto error;
+               if (!chips_p[dest_chip])
+                       goto error;
+               if ((chip_data=((struct ul_usb1_chip_data*)(chips_p[dest_chip]->chip_data)))==NULL)
+                       goto nodata;
+
+               rate=*(int32_t *)(data);
+               sjw=*(int32_t *)(data+4);
+               sampl_pt=*(int32_t *)(data+8);
+               flags=*(int32_t *)(data+12);
+               #if __BYTE_ORDER == __BIG_ENDIAN
+               rate  = bswap_32( rate);
+               sjw  = bswap_32( sjw);
+               sampl_pt  = bswap_32( sampl_pt);
+               flags  = bswap_32( flags);
+               #endif
+
+               if (chips_p[dest_chip]->chipspecops->baud_rate(chips_p[dest_chip], rate, chips_p[dest_chip]->clock, sjw, sampl_pt, flags)<0)
+                       goto error;
+               chip_data->flags |= UL_USB1_CHIP_BAUD_SET;
+       }
+       return 0;
+error:
+       chip_data->flags &= ~UL_USB1_CHIP_BAUD_SET;
+nodata:
+       return -1;
+}
+
+int usbcan_vendor(usb_device_t *udev)
+{
+  // wIndex, wValue, bRequest, wLength
+  int dest_chip;
+  struct ul_usb1_chip_data *chip_data;
+
+  dest_chip=(udev->request.wIndex);
+  if ((dest_chip>=MAX_TOT_CHIPS)||(dest_chip<0))
+       return -1; // Should look like ok (0) or stall (-1)?
+  if (!chips_p[dest_chip])
+       return -1; // Should look like ok (0) or stall (-1)?
+
+  switch ( udev->request.bRequest) {
+               case USBCAN_VENDOR_EXT_MASK_SET:
+                       udev->ep0.complete_fnc=set_ext_mask_complete_fnc;
+                       return 1;
+               case USBCAN_VENDOR_EXT_MASK_STATUS:
+                       vendor_ret=-1;
+                       if ((chip_data=((struct ul_usb1_chip_data*)(chips_p[dest_chip]->chip_data)))==NULL)
+                               usb_send_control_data(udev,&vendor_ret,1);
+                       else{
+                               vendor_ret=(chip_data->flags & UL_USB1_CHIP_MASK_SET)?1:0;
+                               usb_send_control_data(udev,&vendor_ret,1);
+                       }
+                       chip_data->flags &= ~UL_USB1_CHIP_MASK_SET;
+                       return 1;
+
+               case USBCAN_VENDOR_BAUD_RATE_SET:
+                       udev->ep0.complete_fnc=set_baud_rate_complete_fnc;
+                       return 1;
+               case USBCAN_VENDOR_BAUD_RATE_STATUS:
+                       vendor_ret=-1;
+                       if ((chip_data=((struct ul_usb1_chip_data*)(chips_p[dest_chip]->chip_data)))==NULL)
+                               usb_send_control_data(udev,&vendor_ret,1);
+                       else{
+                               vendor_ret=(chip_data->flags & UL_USB1_CHIP_BAUD_SET)?1:0;
+                               usb_send_control_data(udev,&vendor_ret,1);
+                       }
+                       chip_data->flags &= ~UL_USB1_CHIP_BAUD_SET;
+                       return 1;
+
+               case USBCAN_VENDOR_SET_BTREGS:
+                       {
+                               uint16_t value=udev->request.wValue;
+                               vendor_ret=1;
+                               if (chips_p[dest_chip]->chipspecops->set_btregs(chips_p[dest_chip],value&0xFF,(value>>8)&0xFF)<0)
+                                       vendor_ret=0;
+                               usb_send_control_data(udev,&vendor_ret,1);
+                       }
+                       return 1;
+
+               case USBCAN_VENDOR_CHECK_TX_STAT:
+                       {
+                               struct canque_edge_t *qedge;
+                               struct canque_slot_t *slot;
+                               vendor_ret=0;
+                               if (canque_get_inslot(canuser->qends, &qedge, &slot, 0)>=0){
+                                       canque_abort_inslot(canuser->qends, qedge, slot);
+                                       DEBUGMSG("USBCAN_VENDOR_CHECK_TX_STAT - Free slot found\r\n");
+                                       vendor_ret=1;
+                               }
+                               DEBUGMSG("USBCAN_VENDOR_CHECK_TX_STAT - Sending %d\r\n",vendor_ret);
+                               usb_send_control_data(udev,&vendor_ret,1);
+                               return 1;
+                       }
+
+               case USBCAN_VENDOR_START_CHIP:
+                       vendor_ret=1;
+                       if (chips_p[dest_chip]->chipspecops->start_chip(chips_p[dest_chip])<0)
+                               vendor_ret=0;
+                       usb_send_control_data(udev,&vendor_ret,1);
+                       return 1;
+               case USBCAN_VENDOR_STOP_CHIP:
+                       vendor_ret=1;
+                       if (chips_p[dest_chip]->chipspecops->stop_chip(chips_p[dest_chip])<0)
+                               vendor_ret=0;
+                       usb_send_control_data(udev,&vendor_ret,1);
+                       return 1;
+  }
+
+  return 0;
+}
diff --git a/embedded/arch/Makefile b/embedded/arch/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/arch/Makefile.omk b/embedded/arch/Makefile.omk
new file mode 100644 (file)
index 0000000..974732f
--- /dev/null
@@ -0,0 +1,3 @@
+# -*- makefile -*-
+
+SUBDIRS = generic $(ARCH)
diff --git a/embedded/arch/arm/Makefile b/embedded/arch/arm/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/arch/arm/Makefile.omk b/embedded/arch/arm/Makefile.omk
new file mode 100644 (file)
index 0000000..3f99071
--- /dev/null
@@ -0,0 +1 @@
+SUBDIRS = generic mach-$(MACH)
diff --git a/embedded/arch/arm/generic/Makefile b/embedded/arch/arm/generic/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/arch/arm/generic/Makefile.omk b/embedded/arch/arm/generic/Makefile.omk
new file mode 100644 (file)
index 0000000..dba8475
--- /dev/null
@@ -0,0 +1,3 @@
+# -*- makefile -*-
+
+SUBDIRS = defines libs
diff --git a/embedded/arch/arm/generic/defines/Makefile b/embedded/arch/arm/generic/defines/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/arch/arm/generic/defines/Makefile.omk b/embedded/arch/arm/generic/defines/Makefile.omk
new file mode 100644 (file)
index 0000000..702e343
--- /dev/null
@@ -0,0 +1,3 @@
+# -*- makefile -*-
+
+include_HEADERS = $(notdir $(wildcard $(SOURCES_DIR)/*.h))
diff --git a/embedded/arch/arm/generic/defines/cpu_def.h b/embedded/arch/arm/generic/defines/cpu_def.h
new file mode 100644 (file)
index 0000000..8c7b97d
--- /dev/null
@@ -0,0 +1,262 @@
+#ifndef _ARM_CPU_DEF_H
+#define _ARM_CPU_DEF_H
+
+#ifndef CODE
+  #define CODE
+#endif
+
+#ifndef XDATA
+  #define XDATA
+#endif
+
+#ifndef DATA
+  #define DATA
+#endif
+
+struct pt_regs {
+        long uregs[18];
+};
+
+#define ARM_cpsr        uregs[16]
+#define ARM_pc          uregs[15]
+#define ARM_lr          uregs[14]
+#define ARM_sp          uregs[13]
+#define ARM_ip          uregs[12]
+#define ARM_fp          uregs[11]
+#define ARM_r10         uregs[10]
+#define ARM_r9          uregs[9]
+#define ARM_r8          uregs[8]
+#define ARM_r7          uregs[7]
+#define ARM_r6          uregs[6]
+#define ARM_r5          uregs[5]
+#define ARM_r4          uregs[4]
+#define ARM_r3          uregs[3]
+#define ARM_r2          uregs[2]
+#define ARM_r1          uregs[1]
+#define ARM_r0          uregs[0]
+#define ARM_ORIG_r0     uregs[17]
+
+struct undef_hook {
+        struct undef_hook *next;
+        unsigned long instr_mask;
+        unsigned long instr_val;
+        unsigned long cpsr_mask;
+        unsigned long cpsr_val;
+        int (*fn)(struct pt_regs *regs, unsigned int instr);
+};
+
+int register_undef_hook(struct undef_hook *hook);
+
+#define NR_IRQS 256
+
+typedef struct irq_handler {
+  void            (*handler)(int, void *, struct pt_regs *);
+  unsigned long   flags;
+  void            *dev_id;
+  const char      *devname;
+  struct irq_handler *next;
+  short                  vectno;
+} irq_handler_t;
+
+#define        IRQH_ON_LIST    0x100   /* handler is used */
+
+extern irq_handler_t *irq_array[NR_IRQS];
+extern void          *irq_vec[NR_IRQS];
+
+int add_irq_handler(int vectno,irq_handler_t *handler);
+
+int del_irq_handler(int vectno,irq_handler_t *handler);
+
+int test_irq_handler(int vectno,const irq_handler_t *handler);
+
+void irq_redirect2vector(int vectno,struct pt_regs *regs);
+
+/* IRQ handling code */
+
+#define sti()                                                   \
+        ({                                                      \
+                unsigned long temp;                             \
+        __asm__ __volatile__(                                   \
+        "mrs    %0, cpsr                @ sti\n"                \
+"       bic     %0, %0, #128\n"                                 \
+"       msr     cpsr_c, %0"                                     \
+        : "=r" (temp)                                           \
+        :                                                       \
+        : "memory", "cc");                                      \
+        })
+
+#define cli()                                                   \
+        ({                                                      \
+                unsigned long temp;                             \
+        __asm__ __volatile__(                                   \
+        "mrs    %0, cpsr                @ cli\n"                \
+"       orr     %0, %0, #128\n"                                 \
+"       msr     cpsr_c, %0"                                     \
+        : "=r" (temp)                                           \
+        :                                                       \
+        : "memory", "cc");                                      \
+        })
+
+#define save_and_cli(flags)                                     \
+        ({                                                      \
+                unsigned long temp;                             \
+                (void) (&temp == &flags);                       \
+        __asm__ __volatile__(                                   \
+        "mrs    %0, cpsr                @ save_and_cli\n"       \
+"       orr     %1, %0, #128\n"                                 \
+"       msr     cpsr_c, %1"                                     \
+        : "=r" (flags), "=r" (temp)                             \
+        :                                                       \
+        : "memory", "cc");                                      \
+        })
+
+#define save_flags(flags)                                       \
+        ({                                                      \
+        __asm__ __volatile__(                                   \
+        "mrs    %0, cpsr                @ save_flags\n"         \
+        : "=r" (flags)                                          \
+        :                                                       \
+        : "memory", "cc");                                      \
+        })
+
+#define restore_flags(flags)                                    \
+        __asm__ __volatile__(                                   \
+        "msr    cpsr_c, %0              @ restore_flags\n"      \
+        :                                                       \
+        : "r" (flags)                                           \
+        : "memory", "cc")
+
+
+/* FIQ handling code */
+
+#define fiq_sti()                                                   \
+        ({                                                      \
+                unsigned long temp;                             \
+        __asm__ __volatile__(                                   \
+        "mrs    %0, cpsr                @ sti\n"                \
+"       bic     %0, %0, #64\n"                                  \
+"       msr     cpsr_c, %0"                                     \
+        : "=r" (temp)                                           \
+        :                                                       \
+        : "memory", "cc");                                      \
+        })
+
+#define fiq_cli()                                                   \
+        ({                                                      \
+                unsigned long temp;                             \
+        __asm__ __volatile__(                                   \
+        "mrs    %0, cpsr                @ cli\n"                \
+"       orr     %0, %0, #64\n"                                  \
+"       msr     cpsr_c, %0"                                     \
+        : "=r" (temp)                                           \
+        :                                                       \
+        : "memory", "cc");                                      \
+        })
+
+#define fiq_save_and_cli(flags)                                     \
+        ({                                                      \
+                unsigned long temp;                             \
+                (void) (&temp == &flags);                       \
+        __asm__ __volatile__(                                   \
+        "mrs    %0, cpsr                @ save_and_cli\n"       \
+"       orr     %1, %0, #192\n"                                 \
+"       msr     cpsr_c, %1"                                     \
+        : "=r" (flags), "=r" (temp)                             \
+        :                                                       \
+        : "memory", "cc");                                      \
+        })
+
+void __cpu_coherent_range(unsigned long start, unsigned long end);
+
+static inline void flush_icache_range(unsigned long start, unsigned long end)
+{
+       __cpu_coherent_range(start, end);
+}
+
+/* atomic access routines */
+
+//typedef unsigned long atomic_t;
+
+static inline void atomic_clear_mask(unsigned long mask, volatile unsigned long *addr)
+{
+        unsigned long flags;
+
+        save_and_cli(flags);
+        *addr &= ~mask;
+        restore_flags(flags);
+}
+
+static inline void atomic_set_mask(unsigned long mask, volatile unsigned long *addr)
+{
+        unsigned long flags;
+
+        save_and_cli(flags);
+        *addr |= mask;
+        restore_flags(flags);
+}
+
+static inline void set_bit(int nr, volatile unsigned long *addr)
+{
+        unsigned long flags;
+
+        save_and_cli(flags);
+        *addr |= 1<<nr;
+        restore_flags(flags);
+}
+
+static inline void clear_bit(int nr, volatile unsigned long *addr)
+{
+        unsigned long flags;
+
+        save_and_cli(flags);
+        *addr &= ~(1<<nr);
+        restore_flags(flags);
+}
+
+static inline int test_bit(int nr, volatile unsigned long *addr)
+{
+        return ((*addr) & (1<<nr))?1:0;
+}
+
+static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
+{
+        unsigned long flags;
+       long m=(1<<nr);
+        long r;
+
+        save_and_cli(flags);
+        r=*addr;
+       *addr=r|m;
+        restore_flags(flags);
+        return r&m?1:0;
+}
+
+#define __memory_barrier() \
+ __asm__ __volatile__("": : : "memory")
+
+/*masked fields macros*/
+
+#define __val2mfld(mask,val) (((mask)&~((mask)<<1))*(val)&(mask))
+#define __mfld2val(mask,val) (((val)&(mask))/((mask)&~((mask)<<1)))
+
+static inline void outb(unsigned int port, int val) {
+  *(volatile unsigned char *)(port)=val;
+}
+
+static inline unsigned char inb(unsigned int port) {
+  return *(volatile unsigned char *)(port);
+}
+
+#endif /* _ARM_CPU_DEF_H */
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/embedded/arch/arm/generic/defines/hal_intr.h b/embedded/arch/arm/generic/defines/hal_intr.h
new file mode 100644 (file)
index 0000000..68df921
--- /dev/null
@@ -0,0 +1,82 @@
+#ifndef HAL_INTR_H
+#define HAL_INTR_H
+
+#include <hal_ints.h>
+
+//--------------------------------------------------------------------------
+// Static data used by HAL
+// ISR tables
+extern uint32_t hal_interrupt_handlers[HAL_ISR_COUNT];
+extern uint32_t hal_interrupt_data[HAL_ISR_COUNT];
+
+//--------------------------------------------------------------------------
+// Default ISR
+// The #define is used to test whether this routine exists, and to allow
+// code outside the HAL to call it.
+typedef void (*hal_isr)(int vector, uint32_t data); //function ptr
+extern uint32_t hal_default_isr(int vector, uint32_t data);
+#define HAL_DEFAULT_ISR hal_default_isr
+
+//--------------------------------------------------------------------------
+// Vector translation.
+
+#ifndef HAL_TRANSLATE_VECTOR
+#define HAL_TRANSLATE_VECTOR(_vector_,_index_) \
+    (_index_) = (_vector_)
+#endif
+
+//--------------------------------------------------------------------------
+// Interrupt and VSR attachment macros
+
+#define HAL_INTERRUPT_IN_USE( _vector_, _state_)                          \
+    {                                                                     \
+    uint32_t _index_;                                                     \
+    HAL_TRANSLATE_VECTOR ((_vector_), _index_);                           \
+                                                                          \
+    if( hal_interrupt_handlers[_index_] == (uint32_t)hal_default_isr ) \
+        (_state_) = 0;                                                    \
+    else                                                                  \
+        (_state_) = 1;                                                    \
+    }
+
+#define HAL_INTERRUPT_ATTACH( _vector_, _isr_, _data_)                     \
+    {                                                                      \
+    if( hal_interrupt_handlers[_vector_] == (uint32_t)hal_default_isr ) \
+    {                                                                      \
+        hal_interrupt_handlers[_vector_] = (uint32_t)_isr_;             \
+        hal_interrupt_data[_vector_] = (uint32_t) _data_;                  \
+    }                                                                      \
+    }
+
+#define HAL_INTERRUPT_DETACH( _vector_, _isr_ )                            \
+    {                                                                      \
+    if( hal_interrupt_handlers[_vector_] == (uint32_t)_isr_ )           \
+    {                                                                      \
+        hal_interrupt_handlers[_vector_] = (uint32_t)hal_default_isr;   \
+        hal_interrupt_data[_vector_] = 0;                                  \
+    }                                                                      \
+    }
+
+
+//--------------------------------------------------------------------------
+// Interrupt controller access
+
+extern void hal_interrupt_mask(int);
+extern void hal_interrupt_unmask(int);
+extern void hal_interrupt_acknowledge(int);
+extern void hal_interrupt_configure(int, int, int);
+extern void hal_interrupt_set_level(int, int);
+
+#define HAL_INTERRUPT_MASK( _vector_ )                     \
+    hal_interrupt_mask( _vector_ ) 
+#define HAL_INTERRUPT_UNMASK( _vector_ )                   \
+    hal_interrupt_unmask( _vector_ )
+#define HAL_INTERRUPT_ACKNOWLEDGE( _vector_ )              \
+    hal_interrupt_acknowledge( _vector_ )
+#define HAL_INTERRUPT_CONFIGURE( _vector_, _level_, _up_ ) \
+    hal_interrupt_configure( _vector_, _level_, _up_ )
+#define HAL_INTERRUPT_SET_LEVEL( _vector_, _level_ )       \
+    hal_interrupt_set_level( _vector_, _level_ )
+
+#endif /* HAL_DEFAULT_ISR */
diff --git a/embedded/arch/arm/generic/defines/types.h b/embedded/arch/arm/generic/defines/types.h
new file mode 100644 (file)
index 0000000..e5d5a57
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef __ASM_ARM_TYPES_H
+#define __ASM_ARM_TYPES_H
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned short umode_t;
+
+/*
+ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
+ * header files exported to user space
+ */
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+#endif
+
+#endif /* __ASSEMBLY__ */
+
+#ifndef __BIT_TYPES_DEFINED__
+#define __BIT_TYPES_DEFINED__
+
+typedef __u8  uint8_t;
+typedef __s8  int8_t;
+typedef __u16 uint16_t;
+typedef __s16 int16_t;
+typedef __u32 uint32_t;
+typedef __s32 int32_t;
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef __s64 int64_t;
+typedef __u64 uint64_t;
+#endif
+
+#endif /* !(__BIT_TYPES_DEFINED__) */
+
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+#ifdef __KERNEL__
+
+#define BITS_PER_LONG 32
+
+#ifndef __ASSEMBLY__
+
+typedef __s8 s8;
+typedef __u8 u8;
+
+typedef __s16 s16;
+typedef __u16 u16;
+
+typedef __s32 s32;
+typedef __u32 u32;
+
+typedef __s64 s64;
+typedef __s64 u64;
+
+/* Dma addresses are 32-bits wide.  */
+
+typedef u32 dma_addr_t;
+typedef u32 dma64_addr_t;
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __KERNEL__ */
+
+#endif
+
diff --git a/embedded/arch/arm/generic/libs/Makefile b/embedded/arch/arm/generic/libs/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/arch/arm/generic/libs/Makefile.omk b/embedded/arch/arm/generic/libs/Makefile.omk
new file mode 100644 (file)
index 0000000..d833bce
--- /dev/null
@@ -0,0 +1,3 @@
+# -*- makefile -*-
+
+SUBDIRS = misc
diff --git a/embedded/arch/arm/generic/libs/misc/Makefile b/embedded/arch/arm/generic/libs/misc/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/arch/arm/generic/libs/misc/Makefile.omk b/embedded/arch/arm/generic/libs/misc/Makefile.omk
new file mode 100644 (file)
index 0000000..b94858c
--- /dev/null
@@ -0,0 +1,9 @@
+# -*- makefile -*-
+
+include_HEADERS = system_stub.h
+
+lib_LIBRARIES = arch
+
+arch_SOURCES = system_stub.c
+
+lib_obj_SOURCES = system_stub.c
diff --git a/embedded/arch/arm/generic/libs/misc/system_stub.c b/embedded/arch/arm/generic/libs/misc/system_stub.c
new file mode 100644 (file)
index 0000000..24fa2f9
--- /dev/null
@@ -0,0 +1,209 @@
+/* Support files for GNU libc.  Files in the system namespace go here.
+   Files in the C namespace (ie those that do not start with an
+   underscore) go in .c.  */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+#include <stdio.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <errno.h>
+#include <reent.h>
+#include <system_def.h>
+
+/* Register name faking - works in collusion with the linker.  */
+register char * stack_ptr asm ("sp");
+
+system_stub_ops_t system_stub_ops;
+
+int
+_read (int file,
+       char * ptr,
+       int len)
+{
+  if(!system_stub_ops.read)
+    return -1;
+  return system_stub_ops.read(file,ptr,len);
+}
+
+int
+_write (int    file,
+       char * ptr,
+       int    len)
+{
+  if(!system_stub_ops.write)
+    return len;
+  return system_stub_ops.write(file,ptr,len);
+}
+
+
+int
+_lseek (int file,
+       int pos,
+       int dir)
+{
+  if(!system_stub_ops.lseek)
+    return -1;
+  return system_stub_ops.lseek(file,pos,dir);
+}
+
+int
+_open (const char * path,
+       int          flags,
+       ...)
+{
+  if(!system_stub_ops.open)
+    return -1;
+  return system_stub_ops.open(path,flags,0);
+}
+
+int
+_close (int file)
+{
+  if(!system_stub_ops.close)
+    return -1;
+  return system_stub_ops.close(file);
+}
+
+typedef int (local_call_t)(void);
+
+void
+_exit (int n)
+{
+  ((local_call_t*)0)();
+  while(1);
+}
+
+int
+_kill (int n, int m)
+{
+  return -1;
+}
+
+int
+_getpid (int n)
+{
+  return 1;
+}
+
+
+caddr_t
+_sbrk (int incr)
+{
+  extern char   end asm ("end");       /* Defined by the linker.  */
+  static char   *heap_end;
+  char *        prev_heap_end;
+
+  incr=(incr+3) & ~3;
+
+  if (heap_end == NULL)
+    heap_end = & end;
+  
+  prev_heap_end = heap_end;
+    
+  if (heap_end + incr > stack_ptr)
+    {
+      /* Some of the libstdc++-v3 tests rely upon detecting
+        out of memory errors, so do not abort here.  */
+#if 0
+      extern void abort (void);
+
+      _write (1, "_sbrk: Heap and stack collision\n", 32);
+      
+      abort ();
+#else
+      errno = ENOMEM;
+      return (caddr_t) -1;
+#endif
+    }
+  
+  heap_end += incr;
+
+  return (caddr_t) prev_heap_end;
+}
+
+int
+_fstat (int file, struct stat * st)
+{
+  return -1;
+}
+
+int _stat (const char *fname, struct stat *st)
+{
+  return -1;
+}
+
+int
+_link (void)
+{
+  return -1;
+}
+
+int
+_unlink (void)
+{
+  return -1;
+}
+
+void
+_raise (void)
+{
+  return;
+}
+
+int
+_gettimeofday (struct timeval * tp, struct timezone * tzp)
+{
+
+  if(tp) 
+    {
+      tp->tv_sec = 0;
+      tp->tv_usec = 0;
+    }
+  /* Return fixed data for the timezone.  */
+  if (tzp)
+    {
+      tzp->tz_minuteswest = 0;
+      tzp->tz_dsttime = 0;
+    }
+
+  return 0;
+}
+
+/* Return a clock that ticks at 100Hz.  */
+clock_t 
+_times (struct tms * tp)
+{
+  clock_t timeval = 0;
+  
+  if (tp)
+    {
+      tp->tms_utime  = timeval;        /* user time */
+      tp->tms_stime  = 0;      /* system time */
+      tp->tms_cutime = 0;      /* user time, children */
+      tp->tms_cstime = 0;      /* system time, children */
+    }
+  
+  return timeval;
+};
+
+
+int
+isatty (int fd)
+{
+  return 1;
+}
+
+int
+_system (const char *s)
+{
+  return -1;
+}
+
+int
+_rename (const char * oldpath, const char * newpath)
+{
+  return -1;
+}
diff --git a/embedded/arch/arm/generic/libs/misc/system_stub.h b/embedded/arch/arm/generic/libs/misc/system_stub.h
new file mode 100644 (file)
index 0000000..b1e3375
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _SYSTEM_STUB_H_
+#define _SYSTEM_STUB_H_
+
+#include <types.h>
+
+typedef struct system_stub_ops_t {
+  int (*open)(const char * path, int flags, ...);
+  int (*close)(int file);
+  int (*read)(int file, char * ptr, int len);
+  int (*write)(int file, char * ptr, int len);
+  int (*lseek)(int file, int ptr, int dir);
+} system_stub_ops_t;
+
+extern system_stub_ops_t system_stub_ops;
+
+#endif /* _SYSTEM_DEF_H_ */
diff --git a/embedded/arch/arm/generic/libs/misc/undef_support.c b/embedded/arch/arm/generic/libs/misc/undef_support.c
new file mode 100644 (file)
index 0000000..a51b708
--- /dev/null
@@ -0,0 +1,55 @@
+#include <cpu_def.h>
+#include <irq_def.h>
+
+static int undef_initialized = 0;
+
+static unsigned long cpu_undef_stack[256];
+
+struct undef_hook *undef_hook_chain = NULL;
+
+static void undef_exception_handler(int excptnum, struct pt_regs *regs)
+{
+  /*unsigned int correction = thumb_mode(regs) ? 2 : 4;*/
+  unsigned int correction = 0;
+  struct undef_hook *hook;
+  void *pc;
+  unsigned long instr;
+
+  regs->ARM_pc -= correction;
+
+  pc = (void *)regs->ARM_pc;
+
+  instr = *(unsigned long *)pc;
+
+  for(hook = undef_hook_chain; hook; hook = hook->next) {
+    if (((instr & hook->instr_mask) == hook->instr_val) &&
+      ((regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val)) {
+      if (hook->fn(regs, instr) == 0) {
+        return;
+      }
+    }
+  }
+
+  for(;;){
+    /* Fatal error */
+  }
+}
+
+int register_undef_hook(struct undef_hook *hook)
+{
+  unsigned long flags;
+
+  save_and_cli(flags);
+
+  if(!undef_initialized) {
+    set_cpu_exception_handler(ARM_EXCEPTION_UNDEF, (long)undef_exception_handler);
+    set_cpu_exception_stack(ARM_EXCEPTION_UNDEF, (long)((char*)cpu_undef_stack+sizeof(cpu_undef_stack)-8));
+    undef_initialized = 1;
+  }
+
+  hook->next = undef_hook_chain;
+  undef_hook_chain = hook;
+  restore_flags(flags);
+  
+  return 0;
+}
diff --git a/embedded/arch/arm/mach-lpc21xx/Makefile b/embedded/arch/arm/mach-lpc21xx/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/arch/arm/mach-lpc21xx/Makefile.omk b/embedded/arch/arm/mach-lpc21xx/Makefile.omk
new file mode 100644 (file)
index 0000000..2ebd5c8
--- /dev/null
@@ -0,0 +1 @@
+SUBDIRS = defines libs
diff --git a/embedded/arch/arm/mach-lpc21xx/defines/LPC210x.h b/embedded/arch/arm/mach-lpc21xx/defines/LPC210x.h
new file mode 100644 (file)
index 0000000..1e4e2f4
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef INC_LPC210x_H
+#define INC_LPC210x_H
+
+#include "LPC21xx.h"
+
+#endif
diff --git a/embedded/arch/arm/mach-lpc21xx/defines/LPC214x.h b/embedded/arch/arm/mach-lpc21xx/defines/LPC214x.h
new file mode 100644 (file)
index 0000000..d6a95d4
--- /dev/null
@@ -0,0 +1,165 @@
+/******************************************************************************
+ *
+ * $RCSfile: LPC214x.h,v $
+ * $Revision: 1.4 $
+ *
+ * Header file for Philips LPC214x ARM Processors 
+ * Copyright 2006 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ *
+ * No guarantees, warrantees, or promises, implied or otherwise.
+ * May be used for hobby or commercial purposes provided copyright
+ * notice remains intact or GPL license is applied.
+ *
+ *****************************************************************************/
+
+#ifndef INC_LPC214x_H
+#define INC_LPC214x_H
+
+///////////////////////////////////////////////////////////////////////////////
+// ISP_RAM2FLASH_BLOCK_SIZE for 210x CPU
+#ifndef ISP_RAM2FLASH_BLOCK_SIZE
+  #define ISP_RAM2FLASH_BLOCK_SIZE     256
+#endif /* ISP_RAM2FLASH_BLOCK_SIZE */
+
+#include "LPC21xx.h"
+
+#include "lpcUSB.h"
+#include "lpcADC-214x.h"
+
+// USB Phase Locked Loop Registers (PLL48)
+#define PLLCON48        SCB->pll48.con    /* Control Register */
+#define PLLCFG48        SCB->pll48.cfg    /* Configuration Register */
+#define PLLSTAT48       SCB->pll48.stat   /* Status Register */
+#define PLLFEED48       SCB->pll48.feed   /* Feed Register */
+
+///////////////////////////////////////////////////////////////////////////////
+// USB Device
+
+#define USBIntSt (*(REG32*)0xE01FC1C0) /* USB Interrupt Status (R/W) */
+
+#if 1
+
+#define USB             ((usbRegs_t *)0xE0090000)
+
+#define USBDevIntSt    USB->DevIntSt
+#define USBDevIntEn    USB->DevIntEn
+#define USBDevIntClr   USB->DevIntClr
+#define USBDevIntSet   USB->DevIntSet
+#define USBDevIntPri   USB->DevIntPri
+#define USBEpIntSt     USB->EpIntSt
+#define USBEpIntEn     USB->EpIntEn
+#define USBEpIntClr    USB->EpIntClr
+#define USBEpIntSet    USB->EpIntSet
+#define USBEpIntPri    USB->EpIntPri
+#define USBReEp                USB->ReEp
+#define USBEpInd       USB->EpInd
+#define USBMaxPSize    USB->MaxPSize
+#define USBRxData      USB->RxData
+#define USBRxPLen      USB->RxPLen
+#define USBTxData      USB->TxData
+#define USBTxPLen      USB->TxPLen
+#define USBCtrl                USB->Ctrl
+#define USBCmdCode     USB->CmdCode
+#define USBCmdData     USB->CmdData
+#define USBDMARSt      USB->DMARSt
+#define USBDMARClr     USB->DMARClr
+#define USBDMARSet     USB->DMARSet
+#define USBUDCAH       USB->UDCAH
+#define USBEpDMASt     USB->EpDMASt
+#define USBEpDMAEn     USB->EpDMAEn
+#define USBEpDMADis    USB->EpDMADis
+#define USBDMAIntSt    USB->DMAIntSt
+#define USBDMAIntEn    USB->DMAIntEn
+#define USBEoTIntSt    USB->EoTIntSt
+#define USBEoTIntClr   USB->EoTIntClr
+#define USBEoTIntSet   USB->EoTIntSet
+#define USBNDDRIntSt   USB->NDDRIntSt
+#define USBNDDRIntClr  USB->NDDRIntClr
+#define USBNDDRIntSet  USB->NDDRIntSet
+#define USBSysErrIntSt USB->SysErrIntSt
+#define USBSysErrIntClr        USB->SysErrIntClr
+#define USBSysErrIntSet        USB->SysErrIntSet
+#define USB_MODULE_ID  USB->MODULE_ID
+# else
+
+#define USB_REGS_BASE             0xE0090000
+
+#define USBDevIntSt    (*(REG32*)(USB_REGS_BASE+USBDevIntSt_o))
+#define USBDevIntEn    (*(REG32*)(USB_REGS_BASE+USBDevIntEn_o))
+#define USBDevIntClr   (*(REG32*)(USB_REGS_BASE+USBDevIntClr_o))
+#define USBDevIntSet   (*(REG32*)(USB_REGS_BASE+USBDevIntSet_o))
+#define USBDevIntPri   (*(REG_8*)(USB_REGS_BASE+USBDevIntPri_o))
+#define USBEpIntSt     (*(REG32*)(USB_REGS_BASE+USBEpIntSt_o))
+#define USBEpIntEn     (*(REG32*)(USB_REGS_BASE+USBEpIntEn_o))
+#define USBEpIntClr    (*(REG32*)(USB_REGS_BASE+USBEpIntClr_o))
+#define USBEpIntSet    (*(REG32*)(USB_REGS_BASE+USBEpIntSet_o))
+#define USBEpIntPri    (*(REG32*)(USB_REGS_BASE+USBEpIntPri_o))
+#define USBReEp                (*(REG32*)(USB_REGS_BASE+USBReEp_o))
+#define USBEpInd       (*(REG32*)(USB_REGS_BASE+USBEpInd_o))
+#define USBMaxPSize    (*(REG32*)(USB_REGS_BASE+USBMaxPSize_o))
+#define USBRxData      (*(REG32*)(USB_REGS_BASE+USBRxData_o))
+#define USBRxPLen      (*(REG32*)(USB_REGS_BASE+USBRxPLen_o))
+#define USBTxData      (*(REG32*)(USB_REGS_BASE+USBTxData_o))
+#define USBTxPLen      (*(REG32*)(USB_REGS_BASE+USBTxPLen_o))
+#define USBCtrl                (*(REG32*)(USB_REGS_BASE+USBCtrl_o))
+#define USBCmdCode     (*(REG32*)(USB_REGS_BASE+USBCmdCode_o))
+#define USBCmdData     (*(REG32*)(USB_REGS_BASE+USBCmdData_o))
+#define USBDMARSt      (*(REG32*)(USB_REGS_BASE+USBDMARSt_o))
+#define USBDMARClr     (*(REG32*)(USB_REGS_BASE+USBDMARClr_o))
+#define USBDMARSet     (*(REG32*)(USB_REGS_BASE+USBDMARSet_o))
+#define USBUDCAH       (*(REG32*)(USB_REGS_BASE+USBUDCAH_o))
+#define USBEpDMASt     (*(REG32*)(USB_REGS_BASE+USBEpDMASt_o))
+#define USBEpDMAEn     (*(REG32*)(USB_REGS_BASE+USBEpDMAEn_o))
+#define USBEpDMADis    (*(REG32*)(USB_REGS_BASE+USBEpDMADis_o))
+#define USBDMAIntSt    (*(REG32*)(USB_REGS_BASE+USBDMAIntSt_o))
+#define USBDMAIntEn    (*(REG32*)(USB_REGS_BASE+USBDMAIntEn_o))
+#define USBEoTIntSt    (*(REG32*)(USB_REGS_BASE+USBEoTIntSt_o))
+#define USBEoTIntClr   (*(REG32*)(USB_REGS_BASE+USBEoTIntClr_o))
+#define USBEoTIntSet   (*(REG32*)(USB_REGS_BASE+USBEoTIntSet_o))
+#define USBNDDRIntSt   (*(REG32*)(USB_REGS_BASE+USBNDDRIntSt_o))
+#define USBNDDRIntClr  (*(REG32*)(USB_REGS_BASE+USBNDDRIntClr_o))
+#define USBNDDRIntSet  (*(REG32*)(USB_REGS_BASE+USBNDDRIntSet_o))
+#define USBSysErrIntSt (*(REG32*)(USB_REGS_BASE+USBSysErrIntSt_o))
+#define USBSysErrIntClr        (*(REG32*)(USB_REGS_BASE+USBSysErrIntClr_o))
+#define USBSysErrIntSet        (*(REG32*)(USB_REGS_BASE+USBSysErrIntSet_o))
+#define USB_MODULE_ID  (*(REG32*)(USB_REGS_BASE+USB_MODULE_ID_o))
+
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////
+// A/D Converter
+#define ADC0             ((adc214xRegs_t *)0xE0034000)
+
+#define AD0CR            ADC0->cr       // Control Register 
+#define AD0GDR           ADC0->gdr     // Global Data Register
+#define AD0GSR           ADC0->gsr     // Global Start Register
+#define AD0INTEN         ADC0->inten   // Interrupt Enable Register
+#define AD0DR0           ADC0->dr0     // Channel 0 Data Register
+#define AD0DR1           ADC0->dr1     // Channel 1 Data Register
+#define AD0DR2           ADC0->dr2     // Channel 2 Data Register
+#define AD0DR3           ADC0->dr3     // Channel 3 Data Register
+#define AD0DR4           ADC0->dr4     // Channel 4 Data Register
+#define AD0DR5           ADC0->dr5     // Channel 5 Data Register
+#define AD0DR6           ADC0->dr6     // Channel 6 Data Register
+#define AD0DR7           ADC0->dr7     // Channel 7 Data Register
+#define AD0STAT          ADC0->stat    // Status Register
+
+#define ADC1             ((adc214xRegs_t *)0xE0060000)
+
+#define AD1CR            ADC0->cr       // Control Register 
+#define AD1GDR           ADC0->gdr     // Global Data Register
+#define AD1GSR           ADC0->gsr     // Global Start Register
+#define AD1INTEN         ADC0->inten   // Interrupt Enable Register
+#define AD1DR0           ADC0->dr0     // Channel 0 Data Register
+#define AD1DR1           ADC0->dr1     // Channel 1 Data Register
+#define AD1DR2           ADC0->dr2     // Channel 2 Data Register
+#define AD1DR3           ADC0->dr3     // Channel 3 Data Register
+#define AD1DR4           ADC0->dr4     // Channel 4 Data Register
+#define AD1DR5           ADC0->dr5     // Channel 5 Data Register
+#define AD1DR6           ADC0->dr6     // Channel 6 Data Register
+#define AD1DR7           ADC0->dr7     // Channel 7 Data Register
+#define AD1STAT          ADC0->stat    // Status Register
+
+
+#endif /*INC_LPC21xx_H*/
diff --git a/embedded/arch/arm/mach-lpc21xx/defines/LPC21xx.h b/embedded/arch/arm/mach-lpc21xx/defines/LPC21xx.h
new file mode 100644 (file)
index 0000000..c9d06c8
--- /dev/null
@@ -0,0 +1,333 @@
+/******************************************************************************
+ *
+ * $RCSfile: LPC21xx.h,v $
+ * $Revision: 1.3 $
+ *
+ * Header file for Philips LPC21xx ARM Processors 
+ * Copyright 2004 R O SoftWare
+ *
+ * No guarantees, warrantees, or promises, implied or otherwise.
+ * May be used for hobby or commercial purposes provided copyright
+ * notice remains intact.
+ *
+ *****************************************************************************/
+#ifndef INC_LPC21xx_H
+#define INC_LPC21xx_H
+
+#define REG_8           volatile unsigned char
+#define REG16           volatile unsigned short
+#define REG32           volatile unsigned long
+
+#include "lpcWD.h"
+#include "lpcTMR.h"
+#include "lpcUART.h"
+#include "lpcI2C.h"
+#include "lpcSPI.h"
+#include "lpcRTC.h"
+#include "lpcGPIO.h"
+#include "lpcPIN.h"
+#include "lpcADC.h"
+#include "lpcSCB.h"
+#include "lpcVIC.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// Keyval
+#define KVPB_CHUNK_SIZE 16
+
+///////////////////////////////////////////////////////////////////////////////
+// ISP_RAM2FLASH_BLOCK_SIZE for CPU - minimal is 512, can be smaller for some CPU
+#ifndef ISP_RAM2FLASH_BLOCK_SIZE
+  #define ISP_RAM2FLASH_BLOCK_SIZE     512
+#endif /* ISP_RAM2FLASH_BLOCK_SIZE */
+
+///////////////////////////////////////////////////////////////////////////////
+// Watchdog
+#define WD              ((wdRegs_t *)0xE0000000)
+
+// Watchdog Registers
+#define WDMOD           WD->mod         /* Watchdog Mode Register */
+#define WDTC            WD->tc          /* Watchdog Time Constant Register */
+#define WDFEED          WD->feed        /* Watchdog Feed Register */
+#define WDTV            WD->tv          /* Watchdog Time Value Register */
+
+///////////////////////////////////////////////////////////////////////////////
+// Timer 0
+#define TMR0            ((pwmTmrRegs_t *)0xE0004000)
+
+// Timer 0 Registers
+#define T0IR            TMR0->ir        /* Interrupt Register */
+#define T0TCR           TMR0->tcr       /* Timer Control Register */
+#define T0TC            TMR0->tc        /* Timer Counter */
+#define T0PR            TMR0->pr        /* Prescale Register */
+#define T0PC            TMR0->pc        /* Prescale Counter Register */
+#define T0MCR           TMR0->mcr       /* Match Control Register */
+#define T0MR0           TMR0->mr0       /* Match Register 0 */
+#define T0MR1           TMR0->mr1       /* Match Register 1 */
+#define T0MR2           TMR0->mr2       /* Match Register 2 */
+#define T0MR3           TMR0->mr3       /* Match Register 3 */
+#define T0CCR           TMR0->ccr       /* Capture Control Register */
+#define T0CR0           TMR0->cr0       /* Capture Register 0 */
+#define T0CR1           TMR0->cr1       /* Capture Register 1 */
+#define T0CR2           TMR0->cr2       /* Capture Register 2 */
+#define T0CR3           TMR0->cr3       /* Capture Register 3 */
+#define T0EMR           TMR0->emr       /* External Match Register */
+
+///////////////////////////////////////////////////////////////////////////////
+// Timer 1
+#define TMR1            ((pwmTmrRegs_t *)0xE0008000)
+
+// Timer 1 Registers
+#define T1IR            TMR1->ir        /* Interrupt Register */
+#define T1TCR           TMR1->tcr       /* Timer Control Register */
+#define T1TC            TMR1->tc        /* Timer Counter */
+#define T1PR            TMR1->pr        /* Prescale Register */
+#define T1PC            TMR1->pc        /* Prescale Counter Register */
+#define T1MCR           TMR1->mcr       /* Match Control Register */
+#define T1MR0           TMR1->mr0       /* Match Register 0 */
+#define T1MR1           TMR1->mr1       /* Match Register 1 */
+#define T1MR2           TMR1->mr2       /* Match Register 2 */
+#define T1MR3           TMR1->mr3       /* Match Register 3 */
+#define T1CCR           TMR1->ccr       /* Capture Control Register */
+#define T1CR0           TMR1->cr0       /* Capture Register 0 */
+#define T1CR1           TMR1->cr1       /* Capture Register 1 */
+#define T1CR2           TMR1->cr2       /* Capture Register 2 */
+#define T1CR3           TMR1->cr3       /* Capture Register 3 */
+#define T1EMR           TMR1->emr       /* External Match Register */
+
+///////////////////////////////////////////////////////////////////////////////
+// Pulse Width Modulator (PWM)
+#define PWM             ((pwmTmrRegs_t *)0xE0014000)
+
+// PWM Registers
+#define PWMIR           PWM->ir         /* Interrupt Register */
+#define PWMTCR          PWM->tcr        /* Timer Control Register */
+#define PWMTC           PWM->tc         /* Timer Counter */
+#define PWMPR           PWM->pr         /* Prescale Register */
+#define PWMPC           PWM->pc         /* Prescale Counter Register */
+#define PWMMCR          PWM->mcr        /* Match Control Register */
+#define PWMMR0          PWM->mr0        /* Match Register 0 */
+#define PWMMR1          PWM->mr1        /* Match Register 1 */
+#define PWMMR2          PWM->mr2        /* Match Register 2 */
+#define PWMMR3          PWM->mr3        /* Match Register 3 */
+#define PWMMR4          PWM->mr4        /* Match Register 4 */
+#define PWMMR5          PWM->mr5        /* Match Register 5 */
+#define PWMMR6          PWM->mr6        /* Match Register 6 */
+#define PWMPCR          PWM->pcr        /* Control Register */
+#define PWMLER          PWM->ler        /* Latch Enable Register */
+
+///////////////////////////////////////////////////////////////////////////////
+// Universal Asynchronous Receiver Transmitter 0 (UART0)
+#define UART0           ((uartRegs_t *)0xE000C000)
+#define U0_PINSEL       (0x00000005)    /* PINSEL0 Value for UART0 */
+#define U0_PINMASK      (0x0000000F)    /* PINSEL0 Mask for UART0 */
+
+// UART0 Registers
+#define U0RBR           UART0->rbr      /* Receive Buffer Register */
+#define U0THR           UART0->thr      /* Transmit Holding Register */
+#define U0IER           UART0->ier      /* Interrupt Enable Register */
+#define U0IIR           UART0->iir      /* Interrupt ID Register */
+#define U0FCR           UART0->fcr      /* FIFO Control Register */
+#define U0LCR           UART0->lcr      /* Line Control Register */
+#define U0LSR           UART0->lsr      /* Line Status Register */
+#define U0SCR           UART0->scr      /* Scratch Pad Register */
+#define U0DLL           UART0->dll      /* Divisor Latch Register (LSB) */
+#define U0DLM           UART0->dlm      /* Divisor Latch Register (MSB) */
+
+///////////////////////////////////////////////////////////////////////////////
+// Universal Asynchronous Receiver Transmitter 1 (UART1)
+#define UART1           ((uartRegs_t *)0xE0010000)
+#define U1_PINSEL       (0x00050000)    /* PINSEL0 Value for UART1 */
+#define U1_PINMASK      (0x000F0000)    /* PINSEL0 Mask for UART1 */
+
+// UART1 Registers
+#define U1RBR           UART1->rbr      /* Receive Buffer Register */
+#define U1THR           UART1->thr      /* Transmit Holding Register */
+#define U1IER           UART1->ier      /* Interrupt Enable Register */
+#define U1IIR           UART1->iir      /* Interrupt ID Register */
+#define U1FCR           UART1->fcr      /* FIFO Control Register */
+#define U1LCR           UART1->lcr      /* Line Control Register */
+#define U1MCR           UART1->mcr      /* MODEM Control Register */
+#define U1LSR           UART1->lsr      /* Line Status Register */
+#define U1MSR           UART1->msr      /* MODEM Status Register */
+#define U1SCR           UART1->scr      /* Scratch Pad Register */
+#define U1DLL           UART1->dll      /* Divisor Latch Register (LSB) */
+#define U1DLM           UART1->dlm      /* Divisor Latch Register (MSB) */
+
+///////////////////////////////////////////////////////////////////////////////
+// I2C Interface
+#define I2C             ((i2cRegs_t *)0xE001C000)
+
+// I2C Registers
+#define I2CONSET        I2C->conset     /* Control Set Register */
+#define I2STAT          I2C->stat       /* Status Register */
+#define I2DAT           I2C->dat        /* Data Register */
+#define I2ADR           I2C->adr        /* Slave Address Register */
+#define I2SCLH          I2C->sclh       /* SCL Duty Cycle Register (high half word) */
+#define I2SCLL          I2C->scll       /* SCL Duty Cycle Register (low half word) */
+#define I2CONCLR        I2C->conclr     /* Control Clear Register */
+
+///////////////////////////////////////////////////////////////////////////////
+// Serial Peripheral Interface 0 (SPI0)
+#define SPI0            ((spiRegs_t *)0xE0020000)
+
+// SPI0 Registers
+#define S0SPCR          SPI0->cr        /* Control Register */
+#define S0SPSR          SPI0->sr        /* Status Register */
+#define S0SPDR          SPI0->dr        /* Data Register */
+#define S0SPCCR         SPI0->ccr       /* Clock Counter Register */
+#define S0SPINT         SPI0->flag      /* Interrupt Flag Register */
+
+///////////////////////////////////////////////////////////////////////////////
+// Serial Peripheral Interface 1 (SPI1)
+#define SPI1            ((spiRegs_t *)0xE0030000)
+
+// SPI1 Registers
+#define S1SPCR          SPI1->cr        /* Control Register */
+#define S1SPSR          SPI1->sr        /* Status Register */
+#define S1SPDR          SPI1->dr        /* Data Register */
+#define S1SPCCR         SPI1->ccr       /* Clock Counter Register */
+#define S1SPINT         SPI1->flag      /* Interrupt Flag Register */
+
+///////////////////////////////////////////////////////////////////////////////
+// Real Time Clock
+#define RTC             ((rtcRegs_t *)0xE0024000)
+
+// RTC Registers
+#define RTCILR          RTC->ilr        /* Interrupt Location Register */
+#define RTCCTC          RTC->ctc        /* Clock Tick Counter */
+#define RTCCCR          RTC->ccr        /* Clock Control Register */
+#define RTCCIIR         RTC->ciir       /* Counter Increment Interrupt Register */
+#define RTCAMR          RTC->amr        /* Alarm Mask Register */
+#define RTCCTIME0       RTC->ctime0     /* Consolidated Time Register 0 */
+#define RTCCTIME1       RTC->ctime1     /* Consolidated Time Register 1 */
+#define RTCCTIME2       RTC->ctime2     /* Consolidated Time Register 2 */
+#define RTCSEC          RTC->sec        /* Seconds Register */
+#define RTCMIN          RTC->min        /* Minutes Register */
+#define RTCHOUR         RTC->hour       /* Hours Register */
+#define RTCDOM          RTC->dom        /* Day Of Month Register */
+#define RTCDOW          RTC->dow        /* Day Of Week Register */
+#define RTCDOY          RTC->doy        /* Day Of Year Register */
+#define RTCMONTH        RTC->month      /* Months Register */
+#define RTCYEAR         RTC->year       /* Years Register */
+#define RTCALSEC        RTC->alsec      /* Alarm Seconds Register */
+#define RTCALMIN        RTC->almin      /* Alarm Minutes Register */
+#define RTCALHOUR       RTC->alhour     /* Alarm Hours Register */
+#define RTCALDOM        RTC->aldom      /* Alarm Day Of Month Register */
+#define RTCALDOW        RTC->aldow      /* Alarm Day Of Week Register */
+#define RTCALDOY        RTC->aldoy      /* Alarm Day Of Year Register */
+#define RTCALMON        RTC->almon      /* Alarm Months Register */
+#define RTCALYEAR       RTC->alyear     /* Alarm Years Register */
+#define RTCPREINT       RTC->preint     /* Prescale Value Register (integer) */
+#define RTCPREFRAC      RTC->prefrac    /* Prescale Value Register (fraction) */
+
+///////////////////////////////////////////////////////////////////////////////
+// General Purpose Input/Output
+#define GPIO            ((gpioRegs_t *)0xE0028000)
+
+// GPIO Registers
+#define IO0PIN          GPIO->in0       /* P0 Pin Value Register */
+#define IO0SET          GPIO->set0      /* P0 Pin Output Set Register */
+#define IO0DIR          GPIO->dir0      /* P0 Pin Direction Register */
+#define IO0CLR          GPIO->clr0      /* P0 Pin Output Clear Register */
+#define IO1PIN          GPIO->in1       /* P1 Pin Value Register */
+#define IO1SET          GPIO->set1      /* P1 Pin Output Set Register */
+#define IO1DIR          GPIO->dir1      /* P1 Pin Direction Register */
+#define IO1CLR          GPIO->clr1      /* P1 Pin Output Clear Register */
+
+///////////////////////////////////////////////////////////////////////////////
+// Pin Connect Block
+#define PINSEL          ((pinRegs_t *)0xE002C000)
+
+// Pin Connect Block Registers
+#define PINSEL0         PINSEL->sel0    /* Pin Function Select Register 0 */
+#define PINSEL1         PINSEL->sel1    /* Pin Function Select Register 1 */
+#define PINSEL2         PINSEL->sel2    /* Pin Function Select Register 2 */
+
+///////////////////////////////////////////////////////////////////////////////
+// A/D Converter
+#define ADC             ((adcRegs_t *)0xE0034000)
+
+// A/D Converter Registers
+#define ADCR            ADC->cr         /* Control Register */
+#define ADDR            ADC->dr         /* Data Register */
+
+///////////////////////////////////////////////////////////////////////////////
+// System Contol Block
+#define SCB             ((scbRegs_t *)0xE01FC000)
+
+// Memory Accelerator Module Registers (MAM)
+#define MAMCR           SCB->mam.cr     /* Control Register */
+#define MAMTIM          SCB->mam.tim    /* Timing Control Register */
+
+// Memory Mapping Control Register
+#define MEMMAP          SCB->memmap
+
+// Phase Locked Loop Registers (PLL)
+#define PLLCON          SCB->pll.con    /* Control Register */
+#define PLLCFG          SCB->pll.cfg    /* Configuration Register */
+#define PLLSTAT         SCB->pll.stat   /* Status Register */
+#define PLLFEED         SCB->pll.feed   /* Feed Register */
+
+// Power Control Registers
+#define PCON            SCB->p.con      /* Control Register */
+#define PCONP           SCB->p.conp     /* Peripherals Register */
+
+// VPB Divider Register
+#define VPBDIV          SCB->vpbdiv
+
+// External Interrupt Registers
+#define EXTINT          SCB->ext.flag   /* Flag Register */
+#define EXTWAKE         SCB->ext.wake   /* Wakeup Register */
+#define EXTMODE         SCB->ext.mode   /* Mode Register */
+#define EXTPOLAR        SCB->ext.polar  /* Polarity Register */
+
+///////////////////////////////////////////////////////////////////////////////
+// Vectored Interrupt Controller
+#define VIC             ((vicRegs_t *)0xFFFFF000)
+
+// Vectored Interrupt Controller Registers
+#define VICIRQStatus    VIC->irqStatus  /* IRQ Status Register */
+#define VICFIQStatus    VIC->fiqStatus  /* FIQ Status Register */
+#define VICRawIntr      VIC->rawIntr    /* Raw Interrupt Status Register */
+#define VICIntSelect    VIC->intSelect  /* Interrupt Select Register */
+#define VICIntEnable    VIC->intEnable  /* Interrupt Enable Register */
+#define VICIntEnClear   VIC->intEnClear /* Interrupt Enable Clear Register */
+#define VICSoftInt      VIC->softInt    /* Software Interrupt Register */
+#define VICSoftIntClear VIC->softIntClear /* Software Interrupt Clear Register */
+#define VICProtection   VIC->protection /* Protection Enable Register */
+#define VICVectAddr     VIC->vectAddr   /* Vector Address Register */
+#define VICDefVectAddr  VIC->defVectAddr /* Default Vector Address Register */
+#define VICVectAddr0    VIC->vectAddr0  /* Vector Address 0 Register */
+#define VICVectAddr1    VIC->vectAddr1  /* Vector Address 1 Register */
+#define VICVectAddr2    VIC->vectAddr2  /* Vector Address 2 Register */
+#define VICVectAddr3    VIC->vectAddr3  /* Vector Address 3 Register */
+#define VICVectAddr4    VIC->vectAddr4  /* Vector Address 4 Register */
+#define VICVectAddr5    VIC->vectAddr5  /* Vector Address 5 Register */
+#define VICVectAddr6    VIC->vectAddr6  /* Vector Address 6 Register */
+#define VICVectAddr7    VIC->vectAddr7  /* Vector Address 7 Register */
+#define VICVectAddr8    VIC->vectAddr8  /* Vector Address 8 Register */
+#define VICVectAddr9    VIC->vectAddr9  /* Vector Address 9 Register */
+#define VICVectAddr10   VIC->vectAddr10 /* Vector Address 10 Register */
+#define VICVectAddr11   VIC->vectAddr11 /* Vector Address 11 Register */
+#define VICVectAddr12   VIC->vectAddr12 /* Vector Address 12 Register */
+#define VICVectAddr13   VIC->vectAddr13 /* Vector Address 13 Register */
+#define VICVectAddr14   VIC->vectAddr14 /* Vector Address 14 Register */
+#define VICVectAddr15   VIC->vectAddr15 /* Vector Address 15 Register */
+#define VICVectCntl0    VIC->vectCntl0  /* Vector Control 0 Register */
+#define VICVectCntl1    VIC->vectCntl1  /* Vector Control 1 Register */
+#define VICVectCntl2    VIC->vectCntl2  /* Vector Control 2 Register */
+#define VICVectCntl3    VIC->vectCntl3  /* Vector Control 3 Register */
+#define VICVectCntl4    VIC->vectCntl4  /* Vector Control 4 Register */
+#define VICVectCntl5    VIC->vectCntl5  /* Vector Control 5 Register */
+#define VICVectCntl6    VIC->vectCntl6  /* Vector Control 6 Register */
+#define VICVectCntl7    VIC->vectCntl7  /* Vector Control 7 Register */
+#define VICVectCntl8    VIC->vectCntl8  /* Vector Control 8 Register */
+#define VICVectCntl9    VIC->vectCntl9  /* Vector Control 9 Register */
+#define VICVectCntl10   VIC->vectCntl10 /* Vector Control 10 Register */
+#define VICVectCntl11   VIC->vectCntl11 /* Vector Control 11 Register */
+#define VICVectCntl12   VIC->vectCntl12 /* Vector Control 12 Register */
+#define VICVectCntl13   VIC->vectCntl13 /* Vector Control 13 Register */
+#define VICVectCntl14   VIC->vectCntl14 /* Vector Control 14 Register */
+#define VICVectCntl15   VIC->vectCntl15 /* Vector Control 15 Register */
+
+#endif
diff --git a/embedded/arch/arm/mach-lpc21xx/defines/LPC22xx.h b/embedded/arch/arm/mach-lpc21xx/defines/LPC22xx.h
new file mode 100644 (file)
index 0000000..c2d30e0
--- /dev/null
@@ -0,0 +1,342 @@
+/******************************************************************************
+ *
+ * $RCSfile: LPC22xx.h,v $
+ * $Revision: 1.1 $
+ *
+ * Header file for Philips LPC22xx ARM Processors 
+ * Copyright 2004 R O SoftWare
+ *
+ * No guarantees, warrantees, or promises, implied or otherwise.
+ * May be used for hobby or commercial purposes provided copyright
+ * notice remains intact.
+ *
+ *****************************************************************************/
+#ifndef INC_LPC22xx_H
+#define INC_LPC22xx_H
+
+#define REG_8           volatile unsigned char
+#define REG16           volatile unsigned short
+#define REG32           volatile unsigned long
+
+#include "lpcWD.h"
+#include "lpcTMR.h"
+#include "lpcUART.h"
+#include "lpcI2C.h"
+#include "lpcSPI.h"
+#include "lpcRTC.h"
+#include "lpcGPIO.h"
+#include "lpcPIN.h"
+#include "lpcADC.h"
+#include "lpcSCB.h"
+#include "lpcEMC.h"
+#include "lpcVIC.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// Watchdog
+#define WD              ((wdRegs_t *)0xE0000000)
+
+// Watchdog Registers
+#define WDMOD           WD->mod         /* Watchdog Mode Register */
+#define WDTC            WD->tc          /* Watchdog Time Constant Register */
+#define WDFEED          WD->feed        /* Watchdog Feed Register */
+#define WDTV            WD->tv          /* Watchdog Time Value Register */
+
+///////////////////////////////////////////////////////////////////////////////
+// Timer 0
+#define TMR0            ((pwmTmrRegs_t *)0xE0004000)
+
+// Timer 0 Registers
+#define T0IR            TMR0->ir        /* Interrupt Register */
+#define T0TCR           TMR0->tcr       /* Timer Control Register */
+#define T0TC            TMR0->tc        /* Timer Counter */
+#define T0PR            TMR0->pr        /* Prescale Register */
+#define T0PC            TMR0->pc        /* Prescale Counter Register */
+#define T0MCR           TMR0->mcr       /* Match Control Register */
+#define T0MR0           TMR0->mr0       /* Match Register 0 */
+#define T0MR1           TMR0->mr1       /* Match Register 1 */
+#define T0MR2           TMR0->mr2       /* Match Register 2 */
+#define T0MR3           TMR0->mr3       /* Match Register 3 */
+#define T0CCR           TMR0->ccr       /* Capture Control Register */
+#define T0CR0           TMR0->cr0       /* Capture Register 0 */
+#define T0CR1           TMR0->cr1       /* Capture Register 1 */
+#define T0CR2           TMR0->cr2       /* Capture Register 2 */
+#define T0CR3           TMR0->cr3       /* Capture Register 3 */
+#define T0EMR           TMR0->emr       /* External Match Register */
+
+///////////////////////////////////////////////////////////////////////////////
+// Timer 1
+#define TMR1            ((pwmTmrRegs_t *)0xE0008000)
+
+// Timer 1 Registers
+#define T1IR            TMR1->ir        /* Interrupt Register */
+#define T1TCR           TMR1->tcr       /* Timer Control Register */
+#define T1TC            TMR1->tc        /* Timer Counter */
+#define T1PR            TMR1->pr        /* Prescale Register */
+#define T1PC            TMR1->pc        /* Prescale Counter Register */
+#define T1MCR           TMR1->mcr       /* Match Control Register */
+#define T1MR0           TMR1->mr0       /* Match Register 0 */
+#define T1MR1           TMR1->mr1       /* Match Register 1 */
+#define T1MR2           TMR1->mr2       /* Match Register 2 */
+#define T1MR3           TMR1->mr3       /* Match Register 3 */
+#define T1CCR           TMR1->ccr       /* Capture Control Register */
+#define T1CR0           TMR1->cr0       /* Capture Register 0 */
+#define T1CR1           TMR1->cr1       /* Capture Register 1 */
+#define T1CR2           TMR1->cr2       /* Capture Register 2 */
+#define T1CR3           TMR1->cr3       /* Capture Register 3 */
+#define T1EMR           TMR1->emr       /* External Match Register */
+
+///////////////////////////////////////////////////////////////////////////////
+// Pulse Width Modulator (PWM)
+#define PWM             ((pwmTmrRegs_t *)0xE0014000)
+
+// PWM Registers
+#define PWMIR           PWM->ir         /* Interrupt Register */
+#define PWMTCR          PWM->tcr        /* Timer Control Register */
+#define PWMTC           PWM->tc         /* Timer Counter */
+#define PWMPR           PWM->pr         /* Prescale Register */
+#define PWMPC           PWM->pc         /* Prescale Counter Register */
+#define PWMMCR          PWM->mcr        /* Match Control Register */
+#define PWMMR0          PWM->mr0        /* Match Register 0 */
+#define PWMMR1          PWM->mr1        /* Match Register 1 */
+#define PWMMR2          PWM->mr2        /* Match Register 2 */
+#define PWMMR3          PWM->mr3        /* Match Register 3 */
+#define PWMMR4          PWM->mr4        /* Match Register 4 */
+#define PWMMR5          PWM->mr5        /* Match Register 5 */
+#define PWMMR6          PWM->mr6        /* Match Register 6 */
+#define PWMPCR          PWM->pcr        /* Control Register */
+#define PWMLER          PWM->ler        /* Latch Enable Register */
+
+///////////////////////////////////////////////////////////////////////////////
+// Universal Asynchronous Receiver Transmitter 0 (UART0)
+#define UART0           ((uartRegs_t *)0xE000C000)
+#define U0_PINSEL       (0x00000005)    /* PINSEL0 Value for UART0 */
+#define U0_PINMASK      (0x0000000F)    /* PINSEL0 Mask for UART0 */
+
+// UART0 Registers
+#define U0RBR           UART0->rbr      /* Receive Buffer Register */
+#define U0THR           UART0->thr      /* Transmit Holding Register */
+#define U0IER           UART0->ier      /* Interrupt Enable Register */
+#define U0IIR           UART0->iir      /* Interrupt ID Register */
+#define U0FCR           UART0->fcr      /* FIFO Control Register */
+#define U0LCR           UART0->lcr      /* Line Control Register */
+#define U0LSR           UART0->lsr      /* Line Status Register */
+#define U0SCR           UART0->scr      /* Scratch Pad Register */
+#define U0DLL           UART0->dll      /* Divisor Latch Register (LSB) */
+#define U0DLM           UART0->dlm      /* Divisor Latch Register (MSB) */
+
+///////////////////////////////////////////////////////////////////////////////
+// Universal Asynchronous Receiver Transmitter 1 (UART1)
+#define UART1           ((uartRegs_t *)0xE0010000)
+#define U1_PINSEL       (0x00050000)    /* PINSEL0 Value for UART1 */
+#define U1_PINMASK      (0x000F0000)    /* PINSEL0 Mask for UART1 */
+
+// UART1 Registers
+#define U1RBR           UART1->rbr      /* Receive Buffer Register */
+#define U1THR           UART1->thr      /* Transmit Holding Register */
+#define U1IER           UART1->ier      /* Interrupt Enable Register */
+#define U1IIR           UART1->iir      /* Interrupt ID Register */
+#define U1FCR           UART1->fcr      /* FIFO Control Register */
+#define U1LCR           UART1->lcr      /* Line Control Register */
+#define U1MCR           UART1->mcr      /* MODEM Control Register */
+#define U1LSR           UART1->lsr      /* Line Status Register */
+#define U1MSR           UART1->msr      /* MODEM Status Register */
+#define U1SCR           UART1->scr      /* Scratch Pad Register */
+#define U1DLL           UART1->dll      /* Divisor Latch Register (LSB) */
+#define U1DLM           UART1->dlm      /* Divisor Latch Register (MSB) */
+
+///////////////////////////////////////////////////////////////////////////////
+// I2C Interface
+#define I2C             ((i2cRegs_t *)0xE001C000)
+
+// I2C Registers
+#define I2CONSET        I2C->conset     /* Control Set Register */
+#define I2STAT          I2C->stat       /* Status Register */
+#define I2DAT           I2C->dat        /* Data Register */
+#define I2ADR           I2C->adr        /* Slave Address Register */
+#define I2SCLH          I2C->sclh       /* SCL Duty Cycle Register (high half word) */
+#define I2SCLL          I2C->scll       /* SCL Duty Cycle Register (low half word) */
+#define I2CONCLR        I2C->conclr     /* Control Clear Register */
+
+///////////////////////////////////////////////////////////////////////////////
+// Serial Peripheral Interface 0 (SPI0)
+#define SPI0            ((spiRegs_t *)0xE0020000)
+
+// SPI0 Registers
+#define S0SPCR          SPI0->cr        /* Control Register */
+#define S0SPSR          SPI0->sr        /* Status Register */
+#define S0SPDR          SPI0->dr        /* Data Register */
+#define S0SPCCR         SPI0->ccr       /* Clock Counter Register */
+#define S0SPINT         SPI0->flag      /* Interrupt Flag Register */
+
+///////////////////////////////////////////////////////////////////////////////
+// Serial Peripheral Interface 1 (SPI1)
+#define SPI1            ((spiRegs_t *)0xE0030000)
+
+// SPI1 Registers
+#define S1SPCR          SPI1->cr        /* Control Register */
+#define S1SPSR          SPI1->sr        /* Status Register */
+#define S1SPDR          SPI1->dr        /* Data Register */
+#define S1SPCCR         SPI1->ccr       /* Clock Counter Register */
+#define S1SPINT         SPI1->flag      /* Interrupt Flag Register */
+
+///////////////////////////////////////////////////////////////////////////////
+// Real Time Clock
+#define RTC             ((rtcRegs_t *)0xE0024000)
+
+// RTC Registers
+#define RTCILR          RTC->ilr        /* Interrupt Location Register */
+#define RTCCTC          RTC->ctc        /* Clock Tick Counter */
+#define RTCCCR          RTC->ccr        /* Clock Control Register */
+#define RTCCIIR         RTC->ciir       /* Counter Increment Interrupt Register */
+#define RTCAMR          RTC->amr        /* Alarm Mask Register */
+#define RTCCTIME0       RTC->ctime0     /* Consolidated Time Register 0 */
+#define RTCCTIME1       RTC->ctime1     /* Consolidated Time Register 1 */
+#define RTCCTIME2       RTC->ctime2     /* Consolidated Time Register 2 */
+#define RTCSEC          RTC->sec        /* Seconds Register */
+#define RTCMIN          RTC->min        /* Minutes Register */
+#define RTCHOUR         RTC->hour       /* Hours Register */
+#define RTCDOM          RTC->dom        /* Day Of Month Register */
+#define RTCDOW          RTC->dow        /* Day Of Week Register */
+#define RTCDOY          RTC->doy        /* Day Of Year Register */
+#define RTCMONTH        RTC->month      /* Months Register */
+#define RTCYEAR         RTC->year       /* Years Register */
+#define RTCALSEC        RTC->alsec      /* Alarm Seconds Register */
+#define RTCALMIN        RTC->almin      /* Alarm Minutes Register */
+#define RTCALHOUR       RTC->alhour     /* Alarm Hours Register */
+#define RTCALDOM        RTC->aldom      /* Alarm Day Of Month Register */
+#define RTCALDOW        RTC->aldow      /* Alarm Day Of Week Register */
+#define RTCALDOY        RTC->aldoy      /* Alarm Day Of Year Register */
+#define RTCALMON        RTC->almon      /* Alarm Months Register */
+#define RTCALYEAR       RTC->alyear     /* Alarm Years Register */
+#define RTCPREINT       RTC->preint     /* Prescale Value Register (integer) */
+#define RTCPREFRAC      RTC->prefrac    /* Prescale Value Register (fraction) */
+
+///////////////////////////////////////////////////////////////////////////////
+// General Purpose Input/Output
+#define GPIO            ((gpioRegs_t *)0xE0028000)
+
+// GPIO Registers
+#define IO0PIN          GPIO->in0       /* P0 Pin Value Register */
+#define IO0SET          GPIO->set0      /* P0 Pin Output Set Register */
+#define IO0DIR          GPIO->dir0      /* P0 Pin Direction Register */
+#define IO0CLR          GPIO->clr0      /* P0 Pin Output Clear Register */
+#define IO1PIN          GPIO->in1       /* P1 Pin Value Register */
+#define IO1SET          GPIO->set1      /* P1 Pin Output Set Register */
+#define IO1DIR          GPIO->dir1      /* P1 Pin Direction Register */
+#define IO1CLR          GPIO->clr1      /* P1 Pin Output Clear Register */
+#define IO2PIN          GPIO->in2       /* P2 Pin Value Register */
+#define IO2SET          GPIO->set2      /* P2 Pin Output Set Register */
+#define IO2DIR          GPIO->dir2      /* P2 Pin Direction Register */
+#define IO2CLR          GPIO->clr2      /* P2 Pin Output Clear Register */
+#define IO3PIN          GPIO->in3       /* P3 Pin Value Register */
+#define IO3SET          GPIO->set3      /* P3 Pin Output Set Register */
+#define IO3DIR          GPIO->dir3      /* P3 Pin Direction Register */
+#define IO3CLR          GPIO->clr3      /* P3 Pin Output Clear Register */
+
+///////////////////////////////////////////////////////////////////////////////
+// Pin Connect Block
+#define PINSEL          ((pinRegs_t *)0xE002C000)
+
+// Pin Connect Block Registers
+#define PINSEL0         PINSEL->sel0    /* Pin Function Select Register 0 */
+#define PINSEL1         PINSEL->sel1    /* Pin Function Select Register 1 */
+#define PINSEL2         PINSEL->sel2    /* Pin Function Select Register 2 */
+
+///////////////////////////////////////////////////////////////////////////////
+// A/D Converter
+#define ADC             ((adcRegs_t *)0xE0034000)
+
+// A/D Converter Registers
+#define ADCR            ADC->cr         /* Control Register */
+#define ADDR            ADC->dr         /* Data Register */
+
+///////////////////////////////////////////////////////////////////////////////
+// System Contol Block
+#define SCB             ((scbRegs_t *)0xE01FC000)
+
+// Memory Accelerator Module Registers (MAM)
+#define MAMCR           SCB->mam.cr     /* Control Register */
+#define MAMTIM          SCB->mam.tim    /* Timing Control Register */
+
+// Memory Mapping Control Register
+#define MEMMAP          SCB->memmap
+
+// Phase Locked Loop Registers (PLL)
+#define PLLCON          SCB->pll.con    /* Control Register */
+#define PLLCFG          SCB->pll.cfg    /* Configuration Register */
+#define PLLSTAT         SCB->pll.stat   /* Status Register */
+#define PLLFEED         SCB->pll.feed   /* Feed Register */
+
+// Power Control Registers
+#define PCON            SCB->p.con      /* Control Register */
+#define PCONP           SCB->p.conp     /* Peripherals Register */
+
+// VPB Divider Register
+#define VPBDIV          SCB->vpbdiv
+
+// External Interrupt Registers
+#define EXTINT          SCB->ext.flag   /* Flag Register */
+#define EXTWAKE         SCB->ext.wake   /* Wakeup Register */
+#define EXTMODE         SCB->ext.mode   /* Mode Register */
+#define EXTPOLAR        SCB->ext.polar  /* Polarity Register */
+
+///////////////////////////////////////////////////////////////////////////////
+// External Memory Controller (EMC)
+#define EMC             ((volatile emcRegs_t *)0xFFE00000)
+
+// External Memory Controller Registers
+#define BCFG0           EMC->bcfg0      /* Bank 0 Configuration Register */
+#define BCFG1           EMC->bcfg1      /* Bank 1 Configuration Register */
+#define BCFG2           EMC->bcfg2      /* Bank 2 Configuration Register */
+#define BCFG3           EMC->bcfg3      /* Bank 3 Configuration Register */
+
+///////////////////////////////////////////////////////////////////////////////
+// Vectored Interrupt Controller
+#define VIC             ((vicRegs_t *)0xFFFFF000)
+
+// Vectored Interrupt Controller Registers
+#define VICIRQStatus    VIC->irqStatus  /* IRQ Status Register */
+#define VICFIQStatus    VIC->fiqStatus  /* FIQ Status Register */
+#define VICRawIntr      VIC->rawIntr    /* Raw Interrupt Status Register */
+#define VICIntSelect    VIC->intSelect  /* Interrupt Select Register */
+#define VICIntEnable    VIC->intEnable  /* Interrupt Enable Register */
+#define VICIntEnClear   VIC->intEnClear /* Interrupt Enable Clear Register */
+#define VICSoftInt      VIC->softInt    /* Software Interrupt Register */
+#define VICSoftIntClear VIC->softIntClear /* Software Interrupt Clear Register */
+#define VICProtection   VIC->protection /* Protection Enable Register */
+#define VICVectAddr     VIC->vectAddr   /* Vector Address Register */
+#define VICDefVectAddr  VIC->defVectAddr /* Default Vector Address Register */
+#define VICVectAddr0    VIC->vectAddr0  /* Vector Address 0 Register */
+#define VICVectAddr1    VIC->vectAddr1  /* Vector Address 1 Register */
+#define VICVectAddr2    VIC->vectAddr2  /* Vector Address 2 Register */
+#define VICVectAddr3    VIC->vectAddr3  /* Vector Address 3 Register */
+#define VICVectAddr4    VIC->vectAddr4  /* Vector Address 4 Register */
+#define VICVectAddr5    VIC->vectAddr5  /* Vector Address 5 Register */
+#define VICVectAddr6    VIC->vectAddr6  /* Vector Address 6 Register */
+#define VICVectAddr7    VIC->vectAddr7  /* Vector Address 7 Register */
+#define VICVectAddr8    VIC->vectAddr8  /* Vector Address 8 Register */
+#define VICVectAddr9    VIC->vectAddr9  /* Vector Address 9 Register */
+#define VICVectAddr10   VIC->vectAddr10 /* Vector Address 10 Register */
+#define VICVectAddr11   VIC->vectAddr11 /* Vector Address 11 Register */
+#define VICVectAddr12   VIC->vectAddr12 /* Vector Address 12 Register */
+#define VICVectAddr13   VIC->vectAddr13 /* Vector Address 13 Register */
+#define VICVectAddr14   VIC->vectAddr14 /* Vector Address 14 Register */
+#define VICVectAddr15   VIC->vectAddr15 /* Vector Address 15 Register */
+#define VICVectCntl0    VIC->vectCntl0  /* Vector Control 0 Register */
+#define VICVectCntl1    VIC->vectCntl1  /* Vector Control 1 Register */
+#define VICVectCntl2    VIC->vectCntl2  /* Vector Control 2 Register */
+#define VICVectCntl3    VIC->vectCntl3  /* Vector Control 3 Register */
+#define VICVectCntl4    VIC->vectCntl4  /* Vector Control 4 Register */
+#define VICVectCntl5    VIC->vectCntl5  /* Vector Control 5 Register */
+#define VICVectCntl6    VIC->vectCntl6  /* Vector Control 6 Register */
+#define VICVectCntl7    VIC->vectCntl7  /* Vector Control 7 Register */
+#define VICVectCntl8    VIC->vectCntl8  /* Vector Control 8 Register */
+#define VICVectCntl9    VIC->vectCntl9  /* Vector Control 9 Register */
+#define VICVectCntl10   VIC->vectCntl10 /* Vector Control 10 Register */
+#define VICVectCntl11   VIC->vectCntl11 /* Vector Control 11 Register */
+#define VICVectCntl12   VIC->vectCntl12 /* Vector Control 12 Register */
+#define VICVectCntl13   VIC->vectCntl13 /* Vector Control 13 Register */
+#define VICVectCntl14   VIC->vectCntl14 /* Vector Control 14 Register */
+#define VICVectCntl15   VIC->vectCntl15 /* Vector Control 15 Register */
+
+#endif
diff --git a/embedded/arch/arm/mach-lpc21xx/defines/Makefile b/embedded/arch/arm/mach-lpc21xx/defines/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/arch/arm/mach-lpc21xx/defines/Makefile.omk b/embedded/arch/arm/mach-lpc21xx/defines/Makefile.omk
new file mode 100644 (file)
index 0000000..176b8a6
--- /dev/null
@@ -0,0 +1,2 @@
+# -*- makefile -*-
+include_HEADERS = $(notdir $(wildcard $(SOURCES_DIR)/*.h))
diff --git a/embedded/arch/arm/mach-lpc21xx/defines/armVIC.h b/embedded/arch/arm/mach-lpc21xx/defines/armVIC.h
new file mode 100644 (file)
index 0000000..560a6b4
--- /dev/null
@@ -0,0 +1,157 @@
+/******************************************************************************
+ *
+ * $RCSfile: armVIC.h,v $
+ * $Revision: 1.1 $
+ *
+ * This module provides the interface definitions for setting up and
+ * controlling the various interrupt modes present on the ARM processor.
+ * Copyright 2004, R O SoftWare
+ * No guarantees, warrantees, or promises, implied or otherwise.
+ * May be used for hobby or commercial purposes provided copyright
+ * notice remains intact.
+ *
+ *****************************************************************************/
+#ifndef INC_ARM_VIC_H
+#define INC_ARM_VIC_H
+
+/******************************************************************************
+ *
+ * MACRO Name: ISR_ENTRY()
+ *
+ * Description:
+ *    This MACRO is used upon entry to an ISR.  The current version of
+ *    the gcc compiler for ARM does not produce correct code for
+ *    interrupt routines to operate properly with THUMB code.  The MACRO
+ *    performs the following steps:
+ *
+ *    1 - Adjust address at which execution should resume after servicing
+ *        ISR to compensate for IRQ entry
+ *    2 - Save the non-banked registers r0-r12 and lr onto the IRQ stack.
+ *    3 - Get the status of the interrupted program is in SPSR.
+ *    4 - Push it onto the IRQ stack as well.
+ *
+ *****************************************************************************/
+#define ISR_ENTRY() asm volatile(" sub   lr, lr,#4\n" \
+                                 " stmfd sp!,{r0-r12,lr}\n" \
+                                 " mrs   r1, spsr\n" \
+                                 " stmfd sp!,{r1}")
+
+/******************************************************************************
+ *
+ * MACRO Name: ISR_EXIT()
+ *
+ * Description:
+ *    This MACRO is used to exit an ISR.  The current version of the gcc
+ *    compiler for ARM does not produce correct code for interrupt
+ *    routines to operate properly with THUMB code.  The MACRO performs
+ *    the following steps:
+ *
+ *    1 - Recover SPSR value from stack       
+ *    2 - and restore  its value                   
+ *    3 - Pop the return address & the saved general registers from
+ *        the IRQ stack & return
+ *
+ *****************************************************************************/
+#define ISR_EXIT()  asm volatile(" ldmfd sp!,{r1}\n" \
+                                 " msr   spsr_c,r1\n" \
+                                 " ldmfd sp!,{r0-r12,pc}^")
+
+/******************************************************************************
+ *
+ * Function Name: disableIRQ()
+ *
+ * Description:
+ *    This function sets the IRQ disable bit in the status register
+ *
+ * Calling Sequence: 
+ *    void
+ *
+ * Returns:
+ *    previous value of CPSR
+ *
+ *****************************************************************************/
+unsigned disableIRQ(void);
+
+/******************************************************************************
+ *
+ * Function Name: enableIRQ()
+ *
+ * Description:
+ *    This function clears the IRQ disable bit in the status register
+ *
+ * Calling Sequence: 
+ *    void
+ *
+ * Returns:
+ *    previous value of CPSR
+ *
+ *****************************************************************************/
+unsigned enableIRQ(void);
+
+/******************************************************************************
+ *
+ * Function Name: restoreIRQ()
+ *
+ * Description:
+ *    This function restores the IRQ disable bit in the status register
+ *    to the value contained within passed oldCPSR
+ *
+ * Calling Sequence: 
+ *    void
+ *
+ * Returns:
+ *    previous value of CPSR
+ *
+ *****************************************************************************/
+unsigned restoreIRQ(unsigned oldCPSR);
+
+/******************************************************************************
+ *
+ * Function Name: disableFIQ()
+ *
+ * Description:
+ *    This function sets the FIQ disable bit in the status register
+ *
+ * Calling Sequence: 
+ *    void
+ *
+ * Returns:
+ *    previous value of CPSR
+ *
+ *****************************************************************************/
+unsigned disableFIQ(void);
+
+/******************************************************************************
+ *
+ * Function Name: enableFIQ()
+ *
+ * Description:
+ *    This function clears the FIQ disable bit in the status register
+ *
+ * Calling Sequence: 
+ *    void
+ *
+ * Returns:
+ *    previous value of CPSR
+ *
+ *****************************************************************************/
+unsigned enableFIQ(void);
+
+/******************************************************************************
+ *
+ * Function Name: restoreIRQ()
+ *
+ * Description:
+ *    This function restores the FIQ disable bit in the status register
+ *    to the value contained within passed oldCPSR
+ *
+ * Calling Sequence: 
+ *    void
+ *
+ * Returns:
+ *    previous value of CPSR
+ *
+ *****************************************************************************/
+unsigned restoreFIQ(unsigned oldCPSR);
+
+#endif
diff --git a/embedded/arch/arm/mach-lpc21xx/defines/lpcADC-214x.h b/embedded/arch/arm/mach-lpc21xx/defines/lpcADC-214x.h
new file mode 100644 (file)
index 0000000..7e66dae
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef INC_LPC_ADC_214x_H
+#define INC_LPC_ADC_214x_H
+
+// A/D Converter Registers
+typedef struct
+{
+  REG32 cr;                     // Control Register
+  REG32 gdr;                   // Global Data Register
+  REG32 gsr;                   // Global Start Register
+  REG32 inten;                 // Interrupt Enable Register
+  REG32 dr0;                   // Channel 0 Data Register
+  REG32 dr1;                   // Channel 1 Data Register
+  REG32 dr2;                   // Channel 2 Data Register
+  REG32 dr3;                   // Channel 3 Data Register
+  REG32 dr4;                   // Channel 4 Data Register
+  REG32 dr5;                   // Channel 5 Data Register
+  REG32 dr6;                   // Channel 6 Data Register
+  REG32 dr7;                   // Channel 7 Data Register
+  REG32 stat;                  // Status Register
+} adc214xRegs_t;
+
+#define        ADCR_SEL                0x000000FF
+#define        ADCR_CLKDIV             0x0000FF00
+#define        ADCR_BURST              0x00010000
+#define        ADCR_CLKS               0x000E0000
+#define        ADCR_PDN                0x00200000
+#define        ADCR_START              0x07000000
+#define        ADCR_EDGE               0x08000000
+
+#define        ADGDR_RESULT            0x0000FFC0
+#define        ADGDR_CHN               0x07000000
+#define        ADGDR_OVERRUN           0x40000000
+#define        ADGDR_DONE              0x80000000
+
+#define        ADGSR_BURST             0x00010000
+#define        ADGSR_START             0x07000000
+#define        ADGSR_EDGE              0x08000000
+
+#define        ADSTAT_DONE             0x000000FF
+#define        ADSTAT_DONE0            0x00000001
+#define        ADSTAT_DONE1            0x00000002
+#define        ADSTAT_DONE2            0x00000004
+#define        ADSTAT_DONE3            0x00000008
+#define        ADSTAT_DONE4            0x00000010
+#define        ADSTAT_DONE5            0x00000020
+#define        ADSTAT_DONE6            0x00000040
+#define        ADSTAT_DONE7            0x00000080
+#define        ADSTAT_OVERRUN          0x0000FF00
+#define        ADSTAT_OVERRUN0         0x00000100
+#define        ADSTAT_OVERRUN1         0x00000200
+#define        ADSTAT_OVERRUN2         0x00000400
+#define        ADSTAT_OVERRUN3         0x00000800
+#define        ADSTAT_OVERRUN4         0x00001000
+#define        ADSTAT_OVERRUN5         0x00002000
+#define        ADSTAT_OVERRUN6         0x00004000
+#define        ADSTAT_OVERRUN7         0x00008000
+#define        ADSTAT_ADINT            0x00010000
+
+#define        ADINTEN_INTEN           0x000000FF
+#define        ADINTEN_INTEN0          0x00000001
+#define        ADINTEN_INTEN1          0x00000002
+#define        ADINTEN_INTEN2          0x00000004
+#define        ADINTEN_INTEN3          0x00000008
+#define        ADINTEN_INTEN4          0x00000010
+#define        ADINTEN_INTEN5          0x00000020
+#define        ADINTEN_INTEN6          0x00000040
+#define        ADINTEN_INTEN7          0x00000080
+#define        ADINTEN_GINTEN          0x00000100
+
+#define        ADDR_RESULT             0x0000FFC0
+#define        ADDR_OVERRUN            0x40000000
+#define        ADDR_DONE               0x80000000
+
+#endif
diff --git a/embedded/arch/arm/mach-lpc21xx/defines/lpcADC.h b/embedded/arch/arm/mach-lpc21xx/defines/lpcADC.h
new file mode 100644 (file)
index 0000000..11bc2a3
--- /dev/null
@@ -0,0 +1,24 @@
+/******************************************************************************
+ *
+ * $RCSfile: lpcADC.h,v $
+ * $Revision: 1.1 $
+ *
+ * Header file for Philips LPC ARM Processors.
+ * Copyright 2004 R O SoftWare
+ *
+ * No guarantees, warrantees, or promises, implied or otherwise.
+ * May be used for hobby or commercial purposes provided copyright
+ * notice remains intact.
+ *
+ *****************************************************************************/
+#ifndef INC_LPC_ADC_H
+#define INC_LPC_ADC_H
+
+// A/D Converter Registers
+typedef struct
+{
+  REG32 cr;                             // Control Register
+  REG32 dr;                             // Data Register
+} adcRegs_t;
+
+#endif
diff --git a/embedded/arch/arm/mach-lpc21xx/defines/lpcEMC.h b/embedded/arch/arm/mach-lpc21xx/defines/lpcEMC.h
new file mode 100644 (file)
index 0000000..2349617
--- /dev/null
@@ -0,0 +1,26 @@
+/******************************************************************************
+ *
+ * $RCSfile: lpcEMC.h,v $
+ * $Revision: 1.1 $
+ *
+ * Header file for Philips LPC ARM Processors.
+ * Copyright 2004 R O SoftWare
+ *
+ * No guarantees, warrantees, or promises, implied or otherwise.
+ * May be used for hobby or commercial purposes provided copyright
+ * notice remains intact.
+ *
+ *****************************************************************************/
+#ifndef INC_LPC_EMC_H
+#define INC_LPC_EMC_H
+
+// External Memory Controller Registers
+typedef struct
+{
+  REG32 bcfg0;                          // Bank 0 Configuration Register
+  REG32 bcfg1;                          // Bank 1 Configuration Register
+  REG32 bcfg2;                          // Bank 2 Configuration Register
+  REG32 bcfg3;                          // Bank 3 Configuration Register
+} emcRegs_t;
+
+#endif
diff --git a/embedded/arch/arm/mach-lpc21xx/defines/lpcGPIO.h b/embedded/arch/arm/mach-lpc21xx/defines/lpcGPIO.h
new file mode 100644 (file)
index 0000000..f4c78c9
--- /dev/null
@@ -0,0 +1,38 @@
+/******************************************************************************
+ *
+ * $RCSfile: lpcGPIO.h,v $
+ * $Revision: 1.1 $
+ *
+ * Header file for Philips LPC ARM Processors.
+ * Copyright 2004 R O SoftWare
+ *
+ * No guarantees, warrantees, or promises, implied or otherwise.
+ * May be used for hobby or commercial purposes provided copyright
+ * notice remains intact.
+ *
+ *****************************************************************************/
+#ifndef INC_LPC_GPIO_H
+#define INC_LPC_GPIO_H
+
+// General Purpose Input/Output Registers (GPIO)
+typedef struct
+{
+  REG32 in0;                            // P0 Pin Value Register
+  REG32 set0;                           // P0 Pin Output Set Register
+  REG32 dir0;                           // P0 Pin Direction Register
+  REG32 clr0;                           // P0 Pin Output Clear Register
+  REG32 in1;                            // P1 Pin Value Register
+  REG32 set1;                           // P1 Pin Output Set Register
+  REG32 dir1;                           // P1 Pin Direction Register
+  REG32 clr1;                           // P1 Pin Output Clear Register
+  REG32 in2;                            // P2 Pin Value Register
+  REG32 set2;                           // P2 Pin Output Set Register
+  REG32 dir2;                           // P2 Pin Direction Register
+  REG32 clr2;                           // P2 Pin Output Clear Register
+  REG32 in3;                            // P3 Pin Value Register
+  REG32 set3;                           // P3 Pin Output Set Register
+  REG32 dir3;                           // P3 Pin Direction Register
+  REG32 clr3;                           // P3 Pin Output Clear Register
+} gpioRegs_t;
+
+#endif
diff --git a/embedded/arch/arm/mach-lpc21xx/defines/lpcI2C.h b/embedded/arch/arm/mach-lpc21xx/defines/lpcI2C.h
new file mode 100644 (file)
index 0000000..e874abc
--- /dev/null
@@ -0,0 +1,36 @@
+/******************************************************************************
+ *
+ * $RCSfile: lpcI2C.h,v $
+ * $Revision: 1.1 $
+ *
+ * Header file for Philips LPC ARM Processors.
+ * Copyright 2004 R O SoftWare
+ *
+ * No guarantees, warrantees, or promises, implied or otherwise.
+ * May be used for hobby or commercial purposes provided copyright
+ * notice remains intact.
+ *
+ *****************************************************************************/
+#ifndef INC_LPC_I2C_H
+#define INC_LPC_I2C_H
+
+// I2C Interface Registers
+typedef struct
+{
+  REG_8 conset;                         // Control Set Register
+  REG_8 _pad0[3];
+  REG_8 stat;                           // Status Register
+  REG_8 _pad1[3];
+  REG_8 dat;                            // Data Register
+  REG_8 _pad2[3];
+  REG_8 adr;                            // Slave Address Register
+  REG_8 _pad3[3];
+  REG16 sclh;                           // SCL Duty Cycle Register (high half word)
+  REG16 _pad4;
+  REG16 scll;                           // SCL Duty Cycle Register (low half word)
+  REG16 _pad5;
+  REG_8 conclr;                         // Control Clear Register
+  REG_8 _pad6[3];
+} i2cRegs_t;
+
+#endif
diff --git a/embedded/arch/arm/mach-lpc21xx/defines/lpcPIN.h b/embedded/arch/arm/mach-lpc21xx/defines/lpcPIN.h
new file mode 100644 (file)
index 0000000..df52b37
--- /dev/null
@@ -0,0 +1,26 @@
+/******************************************************************************
+ *
+ * $RCSfile: lpcPIN.h,v $
+ * $Revision: 1.1 $
+ *
+ * Header file for Philips LPC ARM Processors.
+ * Copyright 2004 R O SoftWare
+ *
+ * No guarantees, warrantees, or promises, implied or otherwise.
+ * May be used for hobby or commercial purposes provided copyright
+ * notice remains intact.
+ *
+ *****************************************************************************/
+#ifndef INC_LPC_PIN_H
+#define INC_LPC_PIN_H
+
+// Pin Connect Block Registers
+typedef struct
+{
+  REG32 sel0;                           // Pin Function Select Register 0
+  REG32 sel1;                           // Pin Function Select Register 1
+  REG32 _pad[3];
+  REG32 sel2;                           // Pin Function Select Register 2
+} pinRegs_t;
+
+#endif
diff --git a/embedded/arch/arm/mach-lpc21xx/defines/lpcRTC.h b/embedded/arch/arm/mach-lpc21xx/defines/lpcRTC.h
new file mode 100644 (file)
index 0000000..f9d9c0b
--- /dev/null
@@ -0,0 +1,70 @@
+/******************************************************************************
+ *
+ * $RCSfile: lpcRTC.h,v $
+ * $Revision: 1.1 $
+ *
+ * Header file for Philips LPC ARM Processors.
+ * Copyright 2004 R O SoftWare
+ *
+ * No guarantees, warrantees, or promises, implied or otherwise.
+ * May be used for hobby or commercial purposes provided copyright
+ * notice remains intact.
+ *
+ *****************************************************************************/
+#ifndef INC_LPC_RTC_H
+#define INC_LPC_RTC_H
+
+typedef struct
+{
+  REG_8 ilr;                            // Interrupt Location Register
+  REG_8 _pad0[3];
+  REG16 ctc;                            // Clock Tick Counter
+  REG16 _pad1;
+  REG_8 ccr;                            // Clock Control Register
+  REG_8 _pad2[3];
+  REG_8 ciir;                           // Counter Increment Interrupt Register
+  REG_8 _pad3[3];
+  REG_8 amr;                            // Alarm Mask Register
+  REG_8 _pad4[3];
+  REG32 ctime0;                         // Consolidated Time Register 0
+  REG32 ctime1;                         // Consolidated Time Register 1
+  REG32 ctime2;                         // Consolidated Time Register 2
+  REG_8 sec;                            // Seconds Register
+  REG_8 _pad5[3];
+  REG_8 min;                            // Minutes Register
+  REG_8 _pad6[3];
+  REG_8 hour;                           // Hours Register
+  REG_8 _pad7[3];
+  REG_8 dom;                            // Day Of Month Register
+  REG_8 _pad8[3];
+  REG_8 dow;                            // Day Of Week Register
+  REG_8 _pad9[3];
+  REG16 doy;                            // Day Of Year Register
+  REG16 _pad10;
+  REG_8 month;                          // Months Register
+  REG_8 _pad11[3];
+  REG16 year;                           // Years Register
+  REG32 _pad12[8];
+  REG_8 alsec;                          // Alarm Seconds Register
+  REG_8 _pad13[3];
+  REG_8 almin;                          // Alarm Minutes Register
+  REG_8 _pad14[3];
+  REG_8 alhour;                         // Alarm Hours Register
+  REG_8 _pad15[3];
+  REG_8 aldom;                          // Alarm Day Of Month Register
+  REG_8 _pad16[3];
+  REG_8 aldow;                          // Alarm Day Of Week Register
+  REG_8 _pad17[3];
+  REG16 aldoy;                          // Alarm Day Of Year Register
+  REG16 _pad18;
+  REG_8 almon;                          // Alarm Months Register
+  REG_8 _pad19[3];
+  REG16 alyear;                         // Alarm Years Register
+  REG16 _pad20;
+  REG16 preint;                         // Prescale Value Register (integer)
+  REG16 _pad21;
+  REG16 prefrac;                        // Prescale Value Register (fraction)
+  REG16 _pad22;
+} rtcRegs_t;
+
+#endif
diff --git a/embedded/arch/arm/mach-lpc21xx/defines/lpcSCB.h b/embedded/arch/arm/mach-lpc21xx/defines/lpcSCB.h
new file mode 100644 (file)
index 0000000..5612a94
--- /dev/null
@@ -0,0 +1,129 @@
+/******************************************************************************
+ *
+ * $RCSfile: lpcSCB.h,v $
+ * $Revision: 1.2 $
+ *
+ * Header file for Philips LPC ARM Processors.
+ * Copyright 2004 R O SoftWare
+ *
+ * No guarantees, warrantees, or promises, implied or otherwise.
+ * May be used for hobby or commercial purposes provided copyright
+ * notice remains intact.
+ *
+ *****************************************************************************/
+#ifndef INC_LPC_SCB_H
+#define INC_LPC_SCB_H
+
+// System Control Block Registers
+typedef struct
+{
+  // Memory Accelerator Module Registers (MAM)
+  struct
+    {
+    REG_8 cr;                           // Control Register
+    REG_8 _pad0[3];
+    REG_8 tim;                          // Timing Control Register
+    REG32 _pad1[14];
+    } mam;
+
+  // Memory Mapping Control Register
+  REG_8 memmap;
+  REG32 _pad0[15];
+
+  // Phase Locked Loop Registers (PLL)
+  struct
+    {
+    REG_8 con;                          // Control Register
+    REG_8 _pad0[3];
+    REG_8 cfg;                          // Configuration Register
+    REG_8 _pad1[3];
+    REG16 stat;                         // Status Register
+    REG16 _pad2;
+    REG_8 feed;                         // Feed Register
+    REG_8 _pad3[3];
+    REG32 _pad4[4];
+    } pll;
+
+  struct
+    {
+    REG_8 con;                          // Control Register
+    REG_8 _pad0[3];
+    REG_8 cfg;                          // Configuration Register
+    REG_8 _pad1[3];
+    REG16 stat;                         // Status Register
+    REG16 _pad2;
+    REG_8 feed;                         // Feed Register
+    REG_8 _pad3[3];
+    REG32 _pad4[4];
+    } pll48;
+
+  // Power Control Registers
+  struct
+    {
+    REG_8 con;                          // Control Register
+    REG_8 _pad0[3];
+    REG32 conp;                         // Peripherals Register
+    REG32 _pad1[14];
+    } p;
+
+  // VPB Divider Register
+  REG_8 vpbdiv;
+  REG32 _pad1[15];
+
+  // External Interrupt Registers
+  struct
+    {
+    REG_8 flag;                         // Flag Register
+    REG_8 _pad0[3];
+    REG_8 wake;                         // Wakeup Register
+    REG_8 _pad1[3];
+    REG_8 mode;                         // Mode Register
+    REG_8 _pad2[3];
+    REG_8 polar;                        // Polarity Register
+    REG32 _pad3[12];
+    } ext;
+} scbRegs_t;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// MAM defines
+#define MAMCR_OFF     0
+#define MAMCR_PART    1
+#define MAMCR_FULL    2
+
+#define MAMTIM_CYCLES (((CCLK) + 19999999) / 20000000)
+
+///////////////////////////////////////////////////////////////////////////////
+// MEMMAP defines
+#define MEMMAP_BBLK   0                 // Interrupt Vectors in Boot Block
+#define MEMMAP_FLASH  1                 // Interrupt Vectors in Flash
+#define MEMMAP_SRAM   2                 // Interrupt Vectors in SRAM
+
+///////////////////////////////////////////////////////////////////////////////
+// PLL defines & computations
+// Compute the value of PLL_DIV and test range validity
+// FOSC & PLL_MUL should be defined in project configuration file (config.h)
+#ifndef CCLK
+#define CCLK          (FOSC * PLL_MUL)  // CPU Clock Freq.
+#endif
+
+#define FCCO_MAX      (320000000)       // Max CC Osc Freq.
+#define PLL_DIV       (FCCO_MAX / (2 * CCLK)) // PLL Divider
+#define FCCO          (FOSC * PLL_MUL * 2 * PLL_DIV) // CC Osc. Freq.
+
+// PLLCON Register Bit Definitions
+#define PLLCON_PLLE   (1 << 0)          // PLL Enable
+#define PLLCON_PLLC   (1 << 1)          // PLL Connect
+
+// PLLCFG Register Bit Definitions
+#define PLLCFG_MSEL   ((PLL_MUL - 1) << 0) // PLL Multiplier
+#define PLLCFG_PSEL   ((PLL_DIV - 1) << 5) // PLL Divider
+
+// PLLSTAT Register Bit Definitions
+#define PLLSTAT_LOCK  (1 << 10)         // PLL Lock Status Bit
+
+///////////////////////////////////////////////////////////////////////////////
+// VPBDIV defines & computations
+#define VPBDIV_VALUE  (PBSD & 0x03)     // VPBDIV value
+
+#endif
diff --git a/embedded/arch/arm/mach-lpc21xx/defines/lpcSPI.h b/embedded/arch/arm/mach-lpc21xx/defines/lpcSPI.h
new file mode 100644 (file)
index 0000000..9e6bd2b
--- /dev/null
@@ -0,0 +1,72 @@
+/******************************************************************************
+ *
+ * $RCSfile: lpcSPI.h,v $
+ * $Revision: 1.2 $
+ *
+ * Header file for Philips LPC ARM Processors.
+ * Copyright 2004 R O SoftWare
+ *
+ * No guarantees, warrantees, or promises, implied or otherwise.
+ * May be used for hobby or commercial purposes provided copyright
+ * notice remains intact.
+ *
+ *****************************************************************************/
+#ifndef INC_LPC_SPI_H
+#define INC_LPC_SPI_H
+
+// Serial Peripheral Interface Registers (SPI)
+typedef struct
+{
+  REG_8 cr;                             // Control Register
+  REG_8 _pad0[3];
+  REG_8 sr;                             // Status Register
+  REG_8 _pad1[3];
+  REG_8 dr;                             // Data Register
+  REG_8 _pad2[3];
+  REG_8 ccr;                            // Clock Counter Register
+  REG_8 _pad3[3];
+  REG_8 tcr;                            // Test Control Register
+  REG_8 _pad4[3];
+  REG_8 tsr;                            // Test Status Register
+  REG_8 _pad5[3];
+  REG_8 tor;                            // Test Observe Register
+  REG_8 _pad6[3];
+  REG_8 flag;                           // Interrupt Flag Register
+  REG_8 _pad7[3];
+} spiRegs_t;
+
+
+// SPI Control Register
+#define SPCR_BE    (1 << 2)            // BitEnable : If set the SPI controller
+                                       // sends and receives the number of bits
+                                      // selected by bits 11:8.
+#define SPCR_CPHA  (1 << 3)            // Clock phase control
+#define SPCR_CPOL  (1 << 4)            // Clock polarity control.
+#define SPCR_MSTR  (1 << 5)            // Master mode select.
+#define SPCR_LSBF  (1 << 6)            // LSB First controls
+#define SPCR_SPIE  (1 << 7)            // Serial peripheral interrupt enable.
+#define SPCR_BITS  (0xF << 8)          // When bit 2 of this register is 1,
+                                       // this field controls the number of 
+                                      // bits per transfer
+                                      // 1000 :  8 bits per transfer
+                                      // 1001 :  9 bits per transfer
+                                      // 1010 : 10 bits per transfer
+                                      // 1011 : 11 bits per transfer
+                                      // 1100 : 12 bits per transfer
+                                      // 1101 : 13 bits per transfer
+                                      // 1110 : 14 bits per transfer
+                                      // 1111 : 15 bits per transfer
+                                      // 0000 : 16 bits per transfer
+
+//SPI Status Register
+#define SPSR_ABRT  (1 << 3)           // Slave abort.
+#define SPSR_MODF  (1 << 4)           // Mode fault.
+#define SPSR_ROVR  (1 << 5)           // Read overrun.
+#define SPSR_WCOL  (1 << 6)           // Write collision.
+#define SPSR_SPIF  (1 << 7)           // SPI transfer complete flag.
+
+//SPI Interrupt register
+#define SPINT_IF   (1 << 0)           // SPI interrupt flag.
+
+
+#endif
diff --git a/embedded/arch/arm/mach-lpc21xx/defines/lpcTMR.h b/embedded/arch/arm/mach-lpc21xx/defines/lpcTMR.h
new file mode 100644 (file)
index 0000000..cbc7bed
--- /dev/null
@@ -0,0 +1,108 @@
+/******************************************************************************
+ *
+ * $RCSfile: lpcTMR.h,v $
+ * $Revision: 1.2 $
+ *
+ * Header file for Philips LPC ARM Processors.
+ * Copyright 2004 R O SoftWare
+ *
+ * No guarantees, warrantees, or promises, implied or otherwise.
+ * May be used for hobby or commercial purposes provided copyright
+ * notice remains intact.
+ *
+ *****************************************************************************/
+#ifndef INC_LPC_TMR_H
+#define INC_LPC_TMR_H
+
+// Timer & PWM Registers
+typedef struct
+{
+  REG32 ir;                             // Interrupt Register
+  REG32 tcr;                            // Timer Control Register
+  REG32 tc;                             // Timer Counter
+  REG32 pr;                             // Prescale Register
+  REG32 pc;                             // Prescale Counter Register
+  REG32 mcr;                            // Match Control Register
+  REG32 mr0;                            // Match Register 0
+  REG32 mr1;                            // Match Register 1
+  REG32 mr2;                            // Match Register 2
+  REG32 mr3;                            // Match Register 3
+  REG32 ccr;                            // Capture Control Register
+  REG32 cr0;                            // Capture Register 0
+  REG32 cr1;                            // Capture Register 1
+  REG32 cr2;                            // Capture Register 2
+  REG32 cr3;                            // Capture Register 3
+  REG32 emr;                            // External Match Register
+  REG32 mr4;                            // Match Register 4
+  REG32 mr5;                            // Match Register 5
+  REG32 mr6;                            // Match Register 6
+  REG32 pcr;                            // Control Register
+  REG32 ler;                            // Latch Enable Register
+} pwmTmrRegs_t;
+
+// Timer Interrupt Register Bit Definitions
+#define TIR_MR0I    (1 << 0)            // Interrupt flag for match channel 0
+#define TIR_MR1I    (1 << 1)            // Interrupt flag for match channel 1
+#define TIR_MR2I    (1 << 2)            // Interrupt flag for match channel 2
+#define TIR_MR3I    (1 << 3)            // Interrupt flag for match channel 3
+#define TIR_CR0I    (1 << 4)            // Interrupt flag for capture channel 0 event
+#define TIR_CR1I    (1 << 5)            // Interrupt flag for capture channel 1 event
+#define TIR_CR2I    (1 << 6)            // Interrupt flag for capture channel 2 event
+#define TIR_CR3I    (1 << 7)            // Interrupt flag for capture channel 3 event
+
+// PWM Interrupt Register Bit Definitions
+#define PWMIR_MR0I  (1 << 0)            // Interrupt flag for match channel 0
+#define PWMIR_MR1I  (1 << 1)            // Interrupt flag for match channel 1
+#define PWMIR_MR2I  (1 << 2)            // Interrupt flag for match channel 2
+#define PWMIR_MR3I  (1 << 3)            // Interrupt flag for match channel 3
+#define PWMIR_MR4I  (1 << 8)            // Interrupt flag for match channel 4
+#define PWMIR_MR5I  (1 << 9)            // Interrupt flag for match channel 5
+#define PWMIR_MR6I  (1 << 10)           // Interrupt flag for match channel 6
+#define PWMIR_MASK  (0x070F)
+
+// Timer Control Register Bit Definitions
+#define TCR_ENABLE  (1 << 0)
+#define TCR_RESET   (1 << 1)
+
+// PWM Control Register Bit Definitions
+#define PWMCR_ENABLE (1 << 0)
+#define PWMCR_RESET (1 << 1)
+
+// PWM Latch Enable Register Bit Definitions
+#define PWMLER_PWML0E  (1<<0)
+#define PWMLER_PWML1E  (1<<1)
+#define PWMLER_PWML2E  (1<<2)
+#define PWMLER_PWML3E  (1<<3)
+#define PWMLER_PWML4E  (1<<4)
+#define PWMLER_PWML5E  (1<<5)
+#define PWMLER_PWML6E  (1<<6)
+
+// Timer Match Control Register Bit Definitions
+#define TMCR_MR0_I  (1 << 0)            // Enable Interrupt when MR0 matches TC
+#define TMCR_MR0_R  (1 << 1)            // Enable Reset of TC upon MR0 match
+#define TMCR_MR0_S  (1 << 2)            // Enable Stop of TC upon MR0 match
+#define TMCR_MR1_I  (1 << 3)            // Enable Interrupt when MR1 matches TC
+#define TMCR_MR1_R  (1 << 4)            // Enable Reset of TC upon MR1 match
+#define TMCR_MR1_S  (1 << 5)            // Enable Stop of TC upon MR1 match
+#define TMCR_MR2_I  (1 << 6)            // Enable Interrupt when MR2 matches TC
+#define TMCR_MR2_R  (1 << 7)            // Enable Reset of TC upon MR2 match
+#define TMCR_MR2_S  (1 << 8)            // Enable Stop of TC upon MR2 match
+#define TMCR_MR3_I  (1 << 9)            // Enable Interrupt when MR3 matches TC
+#define TMCR_MR3_R  (1 << 10)           // Enable Reset of TC upon MR3 match
+#define TMCR_MR3_S  (1 << 11)           // Enable Stop of TC upon MR3 match
+
+// Timer Capture Control Register Bit Definitions
+#define TCCR_CR0_R (1 << 0)            // Enable Rising edge on CAPn.0 will load TC to CR0
+#define TCCR_CR0_F (1 << 1)            // Enable Falling edge on CAPn.0 will load TC to CR0
+#define TCCR_CR0_I (1 << 2)            // Enable Interrupt on load of CR0
+#define TCCR_CR1_R (1 << 3)            // Enable Rising edge on CAPn.1 will load TC to CR1
+#define TCCR_CR1_F (1 << 4)            // Enable Falling edge on CAPn.1 will load TC to CR1
+#define TCCR_CR1_I (1 << 5)            // Enable Interrupt on load of CR1
+#define TCCR_CR2_R (1 << 6)            // Enable Rising edge on CAPn.2 will load TC to CR2
+#define TCCR_CR2_F (1 << 7)            // Enable Falling edge on CAPn.2 will load TC to CR2
+#define TCCR_CR2_I (1 << 8)            // Enable Interrupt on load of CR2
+#define TCCR_CR3_R (1 << 9)            // Enable Rising edge on CAPn.3 will load TC to CR3
+#define TCCR_CR3_F (1 << 10)           // Enable Falling edge on CAPn.3 will load TC to CR3
+#define TCCR_CR3_I (1 << 11)           // Enable Interrupt on load of CR3
+
+#endif
diff --git a/embedded/arch/arm/mach-lpc21xx/defines/lpcUART.h b/embedded/arch/arm/mach-lpc21xx/defines/lpcUART.h
new file mode 100644 (file)
index 0000000..74e257a
--- /dev/null
@@ -0,0 +1,122 @@
+/******************************************************************************
+ *
+ * $RCSfile: lpcUART.h,v $
+ * $Revision: 1.1 $
+ *
+ * Header file for Philips LPC ARM Processors.
+ * Copyright 2004 R O SoftWare
+ *
+ * No guarantees, warrantees, or promises, implied or otherwise.
+ * May be used for hobby or commercial purposes provided copyright
+ * notice remains intact.
+ *
+ *****************************************************************************/
+#ifndef INC_LPC_UART_H
+#define INC_LPC_UART_H
+
+// Universal Asynchronous Receiver Transmitter Registers
+typedef struct
+{
+  union
+    {
+    REG_8 rbr;                          // Receive Buffer Register
+    REG_8 thr;                          // Transmit Holding Register
+    REG_8 dll;                          // Divisor Latch Register (LSB)
+    REG_8 _pad0[4];
+    };
+
+  union
+    {
+    REG_8 ier;                          // Interrupt Enable Register
+    REG_8 dlm;                          // Divisor Latch Register (MSB)
+    REG_8 _pad1[4];
+    };
+
+  union
+    {
+    REG_8 iir;                          // Interrupt ID Register
+    REG_8 fcr;                          // FIFO Control Register
+    REG_8 _pad2[4];
+    };
+
+  REG_8 lcr;                            // Line Control Registe
+  REG_8 _pad3[3];
+  REG_8 mcr;                            // MODEM Control Register
+  REG_8 _pad4[3];
+  REG_8 lsr;                            // Line Status Register
+  REG_8 _pad5[3];
+  REG_8 msr;                            // MODEM Status Register
+  REG_8 _pad6[3];
+  REG_8 scr;                            // Scratch Pad Register
+  REG_8 _pad7[3];
+} uartRegs_t;
+
+///////////////////////////////////////////////////////////////////////////////
+// UART defines
+
+// Interrupt Enable Register bit definitions
+#define UIER_ERBFI          (1 << 0)    // Enable Receive Data Available Interrupt
+#define UIER_ETBEI          (1 << 1)    // Enable Transmit Holding Register Empty Interrupt
+#define UIER_ELSI           (1 << 2)    // Enable Receive Line Status Interrupt
+#define UIER_EDSSI          (1 << 3)    // Enable MODEM Status Interrupt
+
+// Interrupt ID Register bit definitions
+#define UIIR_NO_INT         (1 << 0)    // NO INTERRUPTS PENDING
+#define UIIR_MS_INT         (0 << 1)    // MODEM Status
+#define UIIR_THRE_INT       (1 << 1)    // Transmit Holding Register Empty
+#define UIIR_RDA_INT        (2 << 1)    // Receive Data Available
+#define UIIR_RLS_INT        (3 << 1)    // Receive Line Status
+#define UIIR_CTI_INT        (6 << 1)    // Character Timeout Indicator
+#define UIIR_ID_MASK        0x0E
+
+// FIFO Control Register bit definitions
+#define UFCR_FIFO_ENABLE    (1 << 0)    // FIFO Enable
+#define UFCR_RX_FIFO_RESET  (1 << 1)    // Reset Receive FIFO
+#define UFCR_TX_FIFO_RESET  (1 << 2)    // Reset Transmit FIFO
+#define UFCR_FIFO_TRIG1     (0 << 6)    // Trigger @ 1 character in FIFO
+#define UFCR_FIFO_TRIG4     (1 << 6)    // Trigger @ 4 characters in FIFO
+#define UFCR_FIFO_TRIG8     (2 << 6)    // Trigger @ 8 characters in FIFO
+#define UFCR_FIFO_TRIG14    (3 << 6)    // Trigger @ 14 characters in FIFO
+
+// Line Control Register bit definitions
+#define ULCR_CHAR_5         (0 << 0)    // 5-bit character length
+#define ULCR_CHAR_6         (1 << 0)    // 6-bit character length
+#define ULCR_CHAR_7         (2 << 0)    // 7-bit character length
+#define ULCR_CHAR_8         (3 << 0)    // 8-bit character length
+#define ULCR_STOP_1         (0 << 2)    // 1 stop bit
+#define ULCR_STOP_2         (1 << 2)    // 2 stop bits
+#define ULCR_PAR_NO         (0 << 3)    // No Parity
+#define ULCR_PAR_ODD        (1 << 3)    // Odd Parity
+#define ULCR_PAR_EVEN       (3 << 3)    // Even Parity
+#define ULCR_PAR_MARK       (5 << 3)    // MARK "1" Parity
+#define ULCR_PAR_SPACE      (7 << 3)    // SPACE "0" Paruty
+#define ULCR_BREAK_ENABLE   (1 << 6)    // Output BREAK line condition
+#define ULCR_DLAB_ENABLE    (1 << 7)    // Enable Divisor Latch Access
+
+// Modem Control Register bit definitions
+#define UMCR_DTR            (1 << 0)    // Data Terminal Ready
+#define UMCR_RTS            (1 << 1)    // Request To Send
+#define UMCR_LB             (1 << 4)    // Loopback
+
+// Line Status Register bit definitions
+#define ULSR_RDR            (1 << 0)    // Receive Data Ready
+#define ULSR_OE             (1 << 1)    // Overrun Error
+#define ULSR_PE             (1 << 2)    // Parity Error
+#define ULSR_FE             (1 << 3)    // Framing Error
+#define ULSR_BI             (1 << 4)    // Break Interrupt
+#define ULSR_THRE           (1 << 5)    // Transmit Holding Register Empty
+#define ULSR_TEMT           (1 << 6)    // Transmitter Empty
+#define ULSR_RXFE           (1 << 7)    // Error in Receive FIFO
+#define ULSR_ERR_MASK       0x1E
+
+// Modem Status Register bit definitions
+#define UMSR_DCTS           (1 << 0)    // Delta Clear To Send
+#define UMSR_DDSR           (1 << 1)    // Delta Data Set Ready
+#define UMSR_TERI           (1 << 2)    // Trailing Edge Ring Indicator
+#define UMSR_DDCD           (1 << 3)    // Delta Data Carrier Detect
+#define UMSR_CTS            (1 << 4)    // Clear To Send
+#define UMSR_DSR            (1 << 5)    // Data Set Ready
+#define UMSR_RI             (1 << 6)    // Ring Indicator
+#define UMSR_DCD            (1 << 7)    // Data Carrier Detect
+
+#endif
diff --git a/embedded/arch/arm/mach-lpc21xx/defines/lpcUSB.h b/embedded/arch/arm/mach-lpc21xx/defines/lpcUSB.h
new file mode 100644 (file)
index 0000000..3f924b5
--- /dev/null
@@ -0,0 +1,229 @@
+/******************************************************************************
+ *
+ * $RCSfile: lpcUSB.h,v $
+ * $Revision: 1.3 $
+ *
+ * Header file for Philips LPC214x USB enabled ARM Processors 
+ * Copyright 2006 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ *
+ * No guarantees, warrantees, or promises, implied or otherwise.
+ * May be used for hobby or commercial purposes provided copyright
+ * notice remains intact or GPL license is applied.
+ *
+ *****************************************************************************/
+
+/* USBIntSt - USB Interrupt Status (R/W) */
+#define   USB_INT_REQ_LP       (1<<0) /*Low priority interrupt line status (RO) */
+#define   USB_INT_REQ_HP       (1<<1) /*High priority interrupt line status. (RO) */
+#define   USB_INT_REQ_DMA      (1<<2) /*DMA interrupt line status. This bit is read only. (LPC2146/8 only) 0*/
+#define   USB_need_clock       (1<<8) /*USB need clock indicator*/
+#define   USB_EN_USB_INTS      (1<<31) /*Enable all USB interrupts*/
+
+/* Device interrupt registers */
+#define USBDevIntSt_o  0x0000  /* USB Device Interrupt Status (RO) */
+#define USBDevIntEn_o  0x0004  /* USB Device Interrupt Enable (R/W) */
+#define USBDevIntClr_o 0x0008  /* USB Device Interrupt Clear (WO) */
+#define USBDevIntSet_o 0x000C  /* USB Device Interrupt Set (WO) */
+#define   USBDevInt_FRAME      (1<<0) /*Frame interrupt @1kHz for ISO transfers*/
+#define   USBDevInt_EP_FAST    (1<<1) /*Fast interrupt transfer for the endpoint*/
+#define   USBDevInt_EP_SLOW    (1<<2) /*Slow interrupt transfer for the endpoint*/
+#define   USBDevInt_DEV_STAT   (1<<3) /*USB Bus reset, USB suspend change or Connect occured*/
+#define   USBDevInt_CCEMTY     (1<<4) /*Command code register is empty/ready for CMD*/
+#define   USBDevInt_CDFULL     (1<<5) /*Command data register is full/data available*/
+#define   USBDevInt_RxENDPKT   (1<<6) /*Current packet in the FIFO is transferred to the CPU*/
+#define   USBDevInt_TxENDPKT   (1<<7) /*TxPacket bytes written to FIFO*/
+#define   USBDevInt_EP_RLZED   (1<<8) /*Endpoints realized after Maxpacket size update*/
+#define   USBDevInt_ERR_INT    (1<<9) /*Error Interrupt - Use Read Error Status Command 0xFB*/
+
+#define USBDevIntPri_o 0x002C  /* USB Device Interrupt Priority (WO) */
+#define   USBDevIntPri_FRAME   (1<<0) /*0/1 FRAME int routed to the low/high priority interrupt line*/
+#define   USBDevIntPri_EP_FAST (1<<1) /*0/1 EP_FAST int routed to the low/high priority line*/
+
+/* Endpoint interrupt registers - bits corresponds to  EP0 to EP31 */
+#define USBEpIntSt_o   0x0030  /* USB Endpoint Interrupt Status (RO) */
+#define USBEpIntEn_o   0x0034  /* USB Endpoint Interrupt Enable (R/W) */
+#define USBEpIntClr_o  0x0038  /* USB Endpoint Interrupt Clear (WO) */
+#define USBEpIntSet_o  0x003C  /* USB Endpoint Interrupt Set (WO) */
+#define USBEpIntPri_o  0x0040  /* USB Endpoint Priority (WO) */
+/* Endpoint realization registers */
+#define USBReEp_o      0x0044  /* USB Realize Endpoint (R/W) */
+#define USBEpInd_o     0x0048  /* USB Endpoint Index (WO) */
+#define   USBEpInd_Ind         0x001F  /* Index for subsequent USBMaxPSize (WO) */
+#define USBMaxPSize_o  0x004C  /* USB MaxPacketSize (R/W) */
+#define   USBMaxPSize_Size     0x03FF  /* The maximum packet size value */
+/* USB transfer registers */
+#define USBRxData_o    0x0018  /* USB Receive Data (RO) */
+#define USBRxPLen_o    0x0020  /* USB Receive Packet Length (RO) */
+#define   USBRxPLen_PKT_LNGTH  (0x03FF) /*Remaining amount of bytes to be read from RAM*/
+#define   USBRxPLen_DV         (1<<10) /*Data valid. 0 only for error ISO packet*/
+#define   USBRxPLen_PKT_RDY    (1<<11) /*Packet length valid and packet is ready for reading*/
+#define USBTxData_o    0x001C  /* USB Transmit Data (WO) */
+#define USBTxPLen_o    0x0024  /* USB Transmit Packet Length (WO) */
+#define   USBTxPLen_PKT_LNGTH  (0x03FF) /*Remaining amount of bytes to be written to the EP_RAM*/
+#define USBCtrl_o      0x0028  /* USB Control (R/W) */
+#define   USBCtrl_RD_EN                (1<<0) /*Read mode control*/
+#define   USBCtrl_WR_EN                (1<<1) /*Write mode control*/
+#define   USBCtrl_LOG_ENDPOINT 0x003C /*Logical Endpoint number*/
+/* Command registers */
+#define USBCmdCode_o   0x0010  /* USB Command Code (WO) */
+#define   USBCmdCode_CMD_PHASE 0x0000FF00 /*The command phase*/
+#define   USBCmdCode_CMD_CODE  0x00FF0000 /*The code for the command*/
+#define USBCmdData_o   0x0014  /* USB Command Data (RO) */
+/* DMA registers (LPC2146/8 only) */
+#define USBDMARSt_o    0x0050  /* USB DMA Request Status (RO) */
+#define USBDMARClr_o   0x0054  /* USB DMA Request Clear (WO) */
+#define USBDMARSet_o   0x0058  /* USB DMA Request Set (WO) */
+#define USBUDCAH_o     0x0080  /* USB UDCA Head (R/W) has to be aligned to 128 bytes */
+#define USBEpDMASt_o   0x0084  /* USB Endpoint DMA Status (RO) */
+#define USBEpDMAEn_o   0x0088  /* USB Endpoint DMA Enable (WO) */
+#define USBEpDMADis_o  0x008C  /* USB Endpoint DMA Disable (WO) */
+#define USBDMAIntSt_o  0x0090  /* USB DMA Interrupt Status (RO) */
+#define USBDMAIntEn_o  0x0094  /* USB DMA Interrupt Enable (R/W) */
+#define   USBDMAInt_EoT                (1<<0) /*End of Transfer Interrupt bit, 1 if USBEoTIntSt != 0*/
+#define   USBDMAInt_New_DD_Rq  (1<<1) /*  New DD Request Interrupt bit, 1 if USBNDDRIntSt != 0*/
+#define   USBDMAInt_SysError   (1<<2) /*System Error Interrupt bit, 1 if USBSysErrIntSt != 0*/
+#define USBEoTIntSt_o  0x00A0  /* USB End of Transfer Interrupt Status (RO) */
+#define USBEoTIntClr_o 0x00A4  /* USB End of Transfer Interrupt Clear (WO) */
+#define USBEoTIntSet_o 0x00A8  /* USB End of Transfer Interrupt Set (WO) */
+#define USBNDDRIntSt_o 0x00AC  /* USB New DD Request Interrupt Status (RO) */
+#define USBNDDRIntClr_o        0x00B0  /* USB New DD Request Interrupt Clear (WO) */
+#define USBNDDRIntSet_o        0x00B4  /* USB New DD Request Interrupt Set (WO) */
+#define USBSysErrIntSt_o       0x00B8  /* USB System Error Interrupt Status (RO) */
+#define USBSysErrIntClr_o      0x00BC  /* USB System Error Interrupt Clear (WO) */
+#define USBSysErrIntSet_o      0x00C0  /* USB System Error Interrupt Set (WO) */
+#define USB_MODULE_ID_o                0x00FC  /* USB Module ID */
+
+/* Command Codes */
+#define USB_CMD_SET_ADDR        0x00D00500
+#define USB_CMD_CFG_DEV         0x00D80500
+#define USB_CMD_SET_MODE        0x00F30500
+#define USB_CMD_RD_FRAME        0x00F50500
+#define USB_DAT_RD_FRAME        0x00F50200
+#define USB_CMD_RD_TEST         0x00FD0500
+#define USB_DAT_RD_TEST         0x00FD0200
+#define USB_CMD_SET_DEV_STAT    0x00FE0500
+#define USB_CMD_GET_DEV_STAT    0x00FE0500
+#define USB_DAT_GET_DEV_STAT    0x00FE0200
+#define USB_CMD_GET_ERR_CODE    0x00FF0500
+#define USB_DAT_GET_ERR_CODE    0x00FF0200
+#define USB_CMD_RD_ERR_STAT     0x00FB0500
+#define USB_DAT_RD_ERR_STAT     0x00FB0200
+#define USB_DAT_WR_BYTE(x)     (0x00000100 | ((x) << 16))
+#define USB_CMD_SEL_EP(x)      (0x00000500 | ((x) << 16))
+#define USB_DAT_SEL_EP(x)      (0x00000200 | ((x) << 16))
+#define USB_CMD_SEL_EP_CLRI(x) (0x00400500 | ((x) << 16))
+#define USB_DAT_SEL_EP_CLRI(x) (0x00400200 | ((x) << 16))
+#define USB_CMD_SET_EP_STAT(x) (0x00400500 | ((x) << 16))
+#define USB_CMD_CLR_BUF         0x00F20500
+#define USB_DAT_CLR_BUF         0x00F20200
+#define USB_CMD_VALID_BUF       0x00FA0500
+
+/* Device Address Register Definitions */
+#define USBC_DEV_ADDR_MASK       0x7F
+#define USBC_DEV_EN              0x80
+
+/* Device Configure Register Definitions */
+#define USBC_CONF_DEVICE         0x01
+
+/* Device Mode Register Definitions */
+#define USBC_AP_CLK              0x01
+#define USBC_INAK_CI             0x02
+#define USBC_INAK_CO             0x04
+#define USBC_INAK_II             0x08
+#define USBC_INAK_IO             0x10
+#define USBC_INAK_BI             0x20
+#define USBC_INAK_BO             0x40
+
+/* Device Status Register Definitions */
+#define USBC_DEV_CON             0x01
+#define USBC_DEV_CON_CH          0x02
+#define USBC_DEV_SUS             0x04
+#define USBC_DEV_SUS_CH          0x08
+#define USBC_DEV_RST             0x10
+
+/* Error Code Register Definitions */
+#define USBC_ERR_EC_MASK         0x0F
+#define USBC_ERR_EA              0x10
+
+/* Error Status Register Definitions */
+#define USBC_ERR_PID             0x01
+#define USBC_ERR_UEPKT           0x02
+#define USBC_ERR_DCRC            0x04
+#define USBC_ERR_TIMOUT          0x08
+#define USBC_ERR_EOP             0x10
+#define USBC_ERR_B_OVRN          0x20
+#define USBC_ERR_BTSTF           0x40
+#define USBC_ERR_TGL             0x80
+
+/* Endpoint Select Register Definitions */
+#define USBC_EP_SEL_F            0x01
+#define USBC_EP_SEL_ST           0x02
+#define USBC_EP_SEL_STP          0x04
+#define USBC_EP_SEL_PO           0x08
+#define USBC_EP_SEL_EPN          0x10
+#define USBC_EP_SEL_B_1_FULL     0x20
+#define USBC_EP_SEL_B_2_FULL     0x40
+
+/* Endpoint Status Register Definitions */
+#define USBC_EP_STAT_ST          0x01
+#define USBC_EP_STAT_DA          0x20
+#define USBC_EP_STAT_RF_MO       0x40
+#define USBC_EP_STAT_CND_ST      0x80
+
+/* Clear Buffer Register Definitions */
+#define USBC_CLR_BUF_PO          0x01
+
+typedef struct
+{
+/* Device interrupt registers */
+  REG32 DevIntSt;      /* USB Device Interrupt Status (RO) 0000 */
+  REG32 DevIntEn;      /* USB Device Interrupt Enable (R/W) 0004 */
+  REG32 DevIntClr;     /* USB Device Interrupt Clear (WO) 0008 */
+  REG32 DevIntSet;     /* USB Device Interrupt Set (WO) 000C */
+/* Command registers */
+  REG32 CmdCode;       /* USB Command Code (WO) 0010 */
+  REG32 CmdData;       /* USB Command Data (RO) 0014 */
+/* USB transfer registers */
+  REG32 RxData;                /* USB Receive Data (RO) 0018 */
+  REG32 TxData;                /* USB Transmit Data (WO) 001C */
+  REG32 RxPLen;                /* USB Receive Packet Length (RO) 0020 */
+  REG32 TxPLen;                /* USB Transmit Packet Length (WO) 0024 */
+  REG32 Ctrl;          /* USB Control (R/W) 0028 */
+/* Device interrupt priority register */
+  REG_8  USBDevIntPri; /* USB Device Interrupt Priority (WO) 002C */
+  REG_8  _pad0[3];
+/* Endpoint interrupt registers */
+  REG32 EpIntSt;       /* USB Endpoint Interrupt Status (RO) 0030 */
+  REG32 EpIntEn;       /* USB Endpoint Interrupt Enable (R/W) 0034 */
+  REG32 EpIntClr;      /* USB Endpoint Interrupt Clear (WO) 0038 */
+  REG32 EpIntSet;      /* USB Endpoint Interrupt Set (WO) 003C */
+  REG32 EpIntPri;      /* USB Endpoint Priority (WO) 0040 */
+/* Endpoint realization registers */
+  REG32 ReEp;          /* USB Realize Endpoint (R/W) 0044 */
+  REG32 EpInd;         /* USB Endpoint Index (WO) 0048 */
+  REG32 MaxPSize;      /* USB MaxPacketSize (R/W) 004C */
+/* DMA registers (LPC2146/8 only) */
+  REG32 DMARSt;                /* USB DMA Request Status (RO) 0050 */
+  REG32 DMARClr;       /* USB DMA Request Clear (WO) 0054 */
+  REG32 DMARSet;       /* USB DMA Request Set (WO) 0058 */
+  REG32 _pad1[9];
+  REG32 UDCAH;         /* USB UDCA Head (R/W) 0080 */
+  REG32 EpDMASt;       /* USB Endpoint DMA Status (RO) 0084 */
+  REG32 EpDMAEn;       /* USB Endpoint DMA Enable (WO) 0088 */
+  REG32 EpDMADis;      /* USB Endpoint DMA Disable (WO) 008C */
+  REG32 DMAIntSt;      /* USB DMA Interrupt Status (RO) 0090 */
+  REG32 DMAIntEn;      /* USB DMA Interrupt Enable (R/W) 0094 */
+  REG32 _pad2[2];
+  REG32 EoTIntSt;      /* USB End of Transfer Interrupt Status (RO) 00A0 */
+  REG32 EoTIntClr;     /* USB End of Transfer Interrupt Clear (WO) 00A4 */
+  REG32 EoTIntSet;     /* USB End of Transfer Interrupt Set (WO) 00A8 */
+  REG32 NDDRIntSt;     /* USB New DD Request Interrupt Status (RO) 00AC */
+  REG32 NDDRIntClr;    /* USB New DD Request Interrupt Clear (WO) 00B0 */
+  REG32 NDDRIntSet;    /* USB New DD Request Interrupt Set (WO) 00B4 */
+  REG32 SysErrIntSt;   /* USB System Error Interrupt Status (RO) 00B8 */
+  REG32 SysErrIntClr;  /* USB System Error Interrupt Clear (WO) 00BC */
+  REG32 SysErrIntSet;  /* USB System Error Interrupt Set (WO) 00C0 */
+  REG32 _pad3[0xE];
+  REG32 MODULE_ID;     /* Module ID (RO) 00FC */
+} usbRegs_t;
+
diff --git a/embedded/arch/arm/mach-lpc21xx/defines/lpcVIC.h b/embedded/arch/arm/mach-lpc21xx/defines/lpcVIC.h
new file mode 100644 (file)
index 0000000..28d12a6
--- /dev/null
@@ -0,0 +1,95 @@
+/******************************************************************************
+ *
+ * $RCSfile: lpcVIC.h,v $
+ * $Revision: 1.1 $
+ *
+ * Header file for Philips LPC ARM Processors.
+ * Copyright 2004 R O SoftWare
+ *
+ * No guarantees, warrantees, or promises, implied or otherwise.
+ * May be used for hobby or commercial purposes provided copyright
+ * notice remains intact.
+ *
+ *****************************************************************************/
+#ifndef INC_LPC_VIC_H
+#define INC_LPC_VIC_H
+
+// Vectored Interrupt Controller Registers (VIC)
+typedef struct
+{
+  REG32 irqStatus;                      // IRQ Status Register
+  REG32 fiqStatus;                      // FIQ Status Register
+  REG32 rawIntr;                        // Raw Interrupt Status Register
+  REG32 intSelect;                      // Interrupt Select Register
+  REG32 intEnable;                      // Interrupt Enable Register
+  REG32 intEnClear;                     // Interrupt Enable Clear Register
+  REG32 softInt;                        // Software Interrupt Register
+  REG32 softIntClear;                   // Software Interrupt Clear Register
+  REG32 protection;                     // Protection Enable Register
+  REG32 _pad0[3];
+  REG32 vectAddr;                       // Vector Address Register
+  REG32 defVectAddr;                    // Default Vector Address Register
+  REG32 _pad1[50];
+  REG32 vectAddr0;                      // Vector Address 0 Register
+  REG32 vectAddr1;                      // Vector Address 1 Register
+  REG32 vectAddr2;                      // Vector Address 2 Register
+  REG32 vectAddr3;                      // Vector Address 3 Register
+  REG32 vectAddr4;                      // Vector Address 4 Register
+  REG32 vectAddr5;                      // Vector Address 5 Register
+  REG32 vectAddr6;                      // Vector Address 6 Register
+  REG32 vectAddr7;                      // Vector Address 7 Register
+  REG32 vectAddr8;                      // Vector Address 8 Register
+  REG32 vectAddr9;                      // Vector Address 9 Register
+  REG32 vectAddr10;                     // Vector Address 10 Register
+  REG32 vectAddr11;                     // Vector Address 11 Register
+  REG32 vectAddr12;                     // Vector Address 12 Register
+  REG32 vectAddr13;                     // Vector Address 13 Register
+  REG32 vectAddr14;                     // Vector Address 14 Register
+  REG32 vectAddr15;                     // Vector Address 15 Register
+  REG32 _pad2[48];
+  REG32 vectCntl0;                      // Vector Control 0 Register
+  REG32 vectCntl1;                      // Vector Control 1 Register
+  REG32 vectCntl2;                      // Vector Control 2 Register
+  REG32 vectCntl3;                      // Vector Control 3 Register
+  REG32 vectCntl4;                      // Vector Control 4 Register
+  REG32 vectCntl5;                      // Vector Control 5 Register
+  REG32 vectCntl6;                      // Vector Control 6 Register
+  REG32 vectCntl7;                      // Vector Control 7 Register
+  REG32 vectCntl8;                      // Vector Control 8 Register
+  REG32 vectCntl9;                      // Vector Control 9 Register
+  REG32 vectCntl10;                     // Vector Control 10 Register
+  REG32 vectCntl11;                     // Vector Control 11 Register
+  REG32 vectCntl12;                     // Vector Control 12 Register
+  REG32 vectCntl13;                     // Vector Control 13 Register
+  REG32 vectCntl14;                     // Vector Control 14 Register
+  REG32 vectCntl15;                     // Vector Control 15 Register
+} vicRegs_t;
+
+// VIC Channel Assignments
+#define VIC_WDT         0
+#define VIC_TIMER0      4
+#define VIC_TIMER1      5
+#define VIC_UART0       6
+#define VIC_UART1       7
+#define VIC_PWM         8
+#define VIC_PWM0        8
+#define VIC_I2C         9
+#define VIC_SPI         10
+#define VIC_SPI0        10
+#define VIC_SPI1        11
+#define VIC_PLL         12
+#define VIC_RTC         13
+#define VIC_EINT0       14
+#define VIC_EINT1       15
+#define VIC_EINT2       16
+#define VIC_EINT3       17
+#define VIC_ADC         18
+
+// Vector Control Register bit definitions
+#define VIC_ENABLE      (1 << 5)
+
+// Convert Channel Number to Bit Value
+#define VIC_BIT(chan)   (1 << (chan))
+
+#endif
+
diff --git a/embedded/arch/arm/mach-lpc21xx/defines/lpcWD.h b/embedded/arch/arm/mach-lpc21xx/defines/lpcWD.h
new file mode 100644 (file)
index 0000000..65f1d73
--- /dev/null
@@ -0,0 +1,27 @@
+/******************************************************************************
+ *
+ * $RCSfile: lpcWD.h,v $
+ * $Revision: 1.1 $
+ *
+ * Header file for Philips LPC ARM Processors.
+ * Copyright 2004 R O SoftWare
+ *
+ * No guarantees, warrantees, or promises, implied or otherwise.
+ * May be used for hobby or commercial purposes provided copyright
+ * notice remains intact.
+ *
+ *****************************************************************************/
+#ifndef INC_LPC_WD_H
+#define INC_LPC_WD_H
+
+// Watchdog Registers
+typedef struct
+{
+  REG_8 mod;                            // Watchdog Mode Register
+  REG_8 _pad0[3];
+  REG32 tc;                             // Watchdog Time Constant Register
+  REG_8 feed;                           // Watchdog Feed Register
+  REG32 tv;                             // Watchdog Time Value Register
+} wdRegs_t;
+
+#endif
diff --git a/embedded/arch/arm/mach-lpc21xx/libs/Makefile b/embedded/arch/arm/mach-lpc21xx/libs/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/arch/arm/mach-lpc21xx/libs/Makefile.omk b/embedded/arch/arm/mach-lpc21xx/libs/Makefile.omk
new file mode 100644 (file)
index 0000000..778cdc0
--- /dev/null
@@ -0,0 +1,3 @@
+# -*- makefile -*-
+
+SUBDIRS = hal iap 
diff --git a/embedded/arch/arm/mach-lpc21xx/libs/hal/Makefile b/embedded/arch/arm/mach-lpc21xx/libs/hal/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/arch/arm/mach-lpc21xx/libs/hal/Makefile.omk b/embedded/arch/arm/mach-lpc21xx/libs/hal/Makefile.omk
new file mode 100644 (file)
index 0000000..a7917db
--- /dev/null
@@ -0,0 +1,12 @@
+# -*- makefile -*-
+
+lib_obj_SOURCES = startup.S ivt.S
+
+lib_LIBRARIES = mach_hal 
+
+include_HEADERS = hal_ints.h hal_machperiph.h
+
+mach_hal_SOURCES = hal.c hal_machperiph.c
+
+
+
diff --git a/embedded/arch/arm/mach-lpc21xx/libs/hal/hal.c b/embedded/arch/arm/mach-lpc21xx/libs/hal/hal.c
new file mode 100644 (file)
index 0000000..a983e95
--- /dev/null
@@ -0,0 +1,189 @@
+#include <system_def.h>
+#include <hal_ints.h>
+#include <hal_intr.h>
+#include <types.h>
+// -------------------------------------------------------------------------
+// Hardware init
+
+// Return value of VPBDIV register. According to errata doc
+// we need to read twice consecutively to get correct value
+uint32_t lpc_get_vpbdiv(void)
+{   
+    uint32_t vpbdiv_reg;
+
+    vpbdiv_reg=VPBDIV;
+    vpbdiv_reg=VPBDIV;
+
+    return (vpbdiv_reg);
+}
+
+
+// -------------------------------------------------------------------------
+// This routine is called to respond to a hardware interrupt (IRQ).  It
+// should interrogate the hardware and return the IRQ vector number.
+int hal_IRQ_handler(void)
+{
+    uint32_t irq_num, irq_stat;
+
+    irq_stat=VICIRQStatus;
+    for (irq_num = 0; irq_num < 32; irq_num++)
+      if (irq_stat & (1 << irq_num))
+        break;
+    
+    // If not a valid interrrupt source, treat as spurious interrupt    
+    if (irq_num < HAL_ISR_MIN || irq_num > HAL_ISR_MAX)
+      irq_num = HAL_INTERRUPT_NONE;
+    
+    return (irq_num);
+}
+
+
+// -------------------------------------------------------------------------
+// Interrupt control
+//
+
+// Block the the interrupt associated with the vector
+void hal_interrupt_mask(int vector)
+{
+    VICIntEnClear = 1 << vector;
+}
+
+// Unblock the the interrupt associated with the vector
+void hal_interrupt_unmask(int vector)
+{
+    VICIntEnable = 1 << vector;
+}
+
+// Acknowledge the the interrupt associated with the vector. This
+// clears the interrupt but may result in another interrupt being
+// delivered
+void hal_interrupt_acknowledge(int vector)
+{
+
+    // External interrupts have to be cleared from the EXTINT register
+    if (vector >= HAL_INTERRUPT_EINT0 &&
+        vector <= HAL_INTERRUPT_EINT3)
+      {
+        // Map int vector to corresponding bit (0..3)
+        vector = 1 << (vector - HAL_INTERRUPT_EINT0);
+               
+        // Clear the external interrupt
+       EXTINT=vector;
+      }
+    
+    // Acknowledge interrupt in the VIC
+    VICVectAddr=0;
+}
+
+// This provides control over how an interrupt signal is detected.
+// Options are between level or edge sensitive (level) and high/low
+// level or rising/falling edge triggered (up).
+//
+// This should be simple, but unfortunately on some processor revisions,
+// it trips up on two errata issues (for the LPC2294 Rev.A these are
+// EXTINT.1 and VPBDIV.1) and so on these devices a somewhat convoluted
+// sequence in order to work properly. There is nothing in the errata
+// sequence that won't work on a processor without these issues.
+void hal_interrupt_configure(int vector, int level, int up)
+{
+    uint32_t regval;
+#ifdef HAL_ARM_LPC2XXX_EXTINT_ERRATA
+    uint32_t saved_vpbdiv;
+#endif
+
+    // Map int vector to corresponding bit (0..3)
+    vector = 1 << (vector - HAL_INTERRUPT_EINT0);
+    
+#ifdef HAL_ARM_LPC2XXX_EXTINT_ERRATA
+    // From discussions with the Philips applications engineers on the
+    // Yahoo LPC2000 forum, it appears that in order up change both
+    // EXTMODE and EXTPOLAR, the operations have to be performed in
+    // two passes as follows:
+    // old=VPBDIV (x2),
+    //     VPBDIV=0, EXTMODE=n, VPBDIV=n, VPBDIV=0, EXTPOLAR=y, VPBDIV=y
+    // VPCDIV=old
+    
+    // Save current VPBDIV register settings
+    saved_vpbdiv = lpc_get_vpbdiv();
+    
+    // Clear VPBDIV register
+    VPBDIV=0;
+    
+    // Read current mode and update for level (0) or edge detection (1)
+    regval=EXTMODE;
+    if (level)
+      regval &= ~vector;
+    else
+      regval |= vector;
+    EXTMODE=regval;
+    
+    // Set VPBDIV register to same value as mode
+    VPBDIV=regval;
+    
+    // Clear VPBDIV register
+    VPBDIV=0;
+    
+    // Read current polarity and update for trigger level or edge
+    // level: high (1), low (0) edge: rising (1), falling (0)
+    regval=EXTPOLAR;
+    if (up)
+      regval |= vector;
+    else
+      regval &= ~vector;
+    EXTPOLAR=regval;
+      
+    
+    // Set VPBDIV register to same value as mode
+    VPBDIV=regval;
+    
+    // Restore saved VPBDIV register
+    VPBDIV=saved_vpbdiv;
+#else
+    // Read current mode and update for level (0) or edge detection (1)
+    regval=EXTMODE;
+    if (level)
+      regval &= ~vector;
+    else
+      regval |= vector;
+    EXTMODE=regval;
+    
+    // Read current polarity and update for trigger level or edge
+    // level: high (1), low (0) edge: rising (1), falling (0)
+    regval=EXTPOLAR;
+    if (up)
+      regval |= vector;
+    else
+      regval &= ~vector;
+    EXTPOLAR=regval;
+#endif
+    // Clear any spurious interrupt that might have been generated
+    EXTINT=vector;
+}
+
+// Change interrupt level. This is a non-operation on the LPC2XXX
+void hal_interrupt_set_level(int vector, int level)
+{
+}
+
+uint32_t hal_default_isr(int vector, uint32_t data)
+{
+  return 0;
+}
+
+uint32_t hal_interrupt_handlers[HAL_ISR_COUNT]={[0 ... HAL_ISR_COUNT-1]=(uint32_t)hal_default_isr};
+uint32_t hal_interrupt_data[HAL_ISR_COUNT];
+
+void irq_handler_resolver(void) __attribute__ ((interrupt));
+void irq_handler_resolver(void)
+{
+  int v;
+  uint32_t f,d;
+
+  v=hal_IRQ_handler();
+  if (v==HAL_INTERRUPT_NONE) return;
+  f=hal_interrupt_handlers[v];
+  d=hal_interrupt_data[v];
+  ((hal_isr)f)(v,d);  
+  hal_interrupt_acknowledge(v);
+}
diff --git a/embedded/arch/arm/mach-lpc21xx/libs/hal/hal_ints.h b/embedded/arch/arm/mach-lpc21xx/libs/hal/hal_ints.h
new file mode 100644 (file)
index 0000000..d218725
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef HAL_INTS_H
+#define HAL_INTS_H
+
+#define HAL_INTERRUPT_NONE    -1
+
+#define HAL_INTERRUPT_WD      0
+#define HAL_INTERRUPT_SOFT    1
+#define HAL_INTERRUPT_DCC_RX  2
+#define HAL_INTERRUPT_DCC_TX  3
+#define HAL_INTERRUPT_TIMER0  4
+#define HAL_INTERRUPT_TIMER1  5
+#define HAL_INTERRUPT_UART0   6
+#define HAL_INTERRUPT_UART1   7
+#define HAL_INTERRUPT_PWM0    8
+#define HAL_INTERRUPT_I2C0    9
+#define HAL_INTERRUPT_SPI0    10
+#define HAL_INTERRUPT_SPI1    11
+#define HAL_INTERRUPT_PLL     12
+#define HAL_INTERRUPT_RTCDEV  13       
+#define HAL_INTERRUPT_EINT0   14
+#define HAL_INTERRUPT_EINT1   15
+#define HAL_INTERRUPT_EINT2   16
+#define HAL_INTERRUPT_EINT3   17
+#define HAL_INTERRUPT_AD      18 
+#define HAL_INTERRUPT_I2C1    19
+
+#define HAL_ISR_MIN           0
+#define HAL_ISR_MAX           (31)
+
+#define HAL_ISR_COUNT         (HAL_ISR_MAX+1)
+
+//The vector used by the Real time clock
+#define HAL_INTERRUPT_RTC     HAL_INTERRUPT_TIMER0
+
+#endif /* HAL_INTS_H */
diff --git a/embedded/arch/arm/mach-lpc21xx/libs/hal/hal_machperiph.c b/embedded/arch/arm/mach-lpc21xx/libs/hal/hal_machperiph.c
new file mode 100644 (file)
index 0000000..599fdc3
--- /dev/null
@@ -0,0 +1,49 @@
+#include <system_def.h>
+#include <cpu_def.h>
+#include <hal_machperiph.h>
+
+void lpc_pll_on()
+{
+  // set PLL multiplier & divisor.
+  // values computed from config.h
+  PLLCFG = PLLCFG_MSEL | PLLCFG_PSEL;
+
+  // enable PLL
+  PLLCON = PLLCON_PLLE;
+  PLLFEED = 0xAA;                       // Make it happen.  These two updates
+  PLLFEED = 0x55;                       // MUST occur in sequence.
+
+  // wait for PLL lock
+  while (!(PLLSTAT & PLLSTAT_LOCK))
+    continue;
+
+  // enable & connect PLL
+  PLLCON = PLLCON_PLLE | PLLCON_PLLC;
+  PLLFEED = 0xAA;                       // Make it happen.  These two updates
+  PLLFEED = 0x55;                       // MUST occur in sequence.
+}
+
+void lpc_pll_off()
+{
+  // disable PLL
+  PLLCON = 0;
+  PLLFEED = 0xAA;                       // Make it happen.  These two updates
+  PLLFEED = 0x55;                       // MUST occur in sequence.
+}
+
+void lpc_watchdog_feed()
+{
+  unsigned long flags;
+
+  save_and_cli(flags);
+  WDFEED = 0xAA;
+  WDFEED = 0x55;
+  restore_flags(flags);
+}
+
+void lpc_watchdog_init(int on,int timeout_ms)
+{
+  if (!on) return;
+  WDTC = PCLK/(1000/timeout_ms);
+  WDMOD = 0x03;                                   /* Enable watchdog timer and reset */
+}
diff --git a/embedded/arch/arm/mach-lpc21xx/libs/hal/hal_machperiph.h b/embedded/arch/arm/mach-lpc21xx/libs/hal/hal_machperiph.h
new file mode 100644 (file)
index 0000000..9f8c27f
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _HAL_MACHPERIPH_H
+#define _HAL_MACHPERIPH_H
+
+void lpc_pll_on();
+void lpc_pll_off();
+void lpc_watchdog_init(int on,int timeout_ms);
+void lpc_watchdog_feed();
+
+#endif /* _HAL_MACHPERIPH_H */
+
diff --git a/embedded/arch/arm/mach-lpc21xx/libs/hal/ivt.S b/embedded/arch/arm/mach-lpc21xx/libs/hal/ivt.S
new file mode 100644 (file)
index 0000000..ae9032a
--- /dev/null
@@ -0,0 +1,34 @@
+/* Setup vector table.  Note that undf, pabt, dabt, fiq just execute
+a null loop. */
+
+.section .ivt,"ax"
+         .code 32
+         .align 0
+
+         .global hal_vectors
+
+hal_vectors:    LDR     PC, Reset_Addr         
+                LDR     PC, Undef_Addr
+                LDR     PC, SWI_Addr
+                LDR     PC, PAbt_Addr
+                LDR     PC, DAbt_Addr
+                NOP                            /* Reserved Vector */
+                LDR     PC, IRQ_Addr
+                LDR     PC, FIQ_Addr
+
+Reset_Addr:     .word   reset_handler
+Undef_Addr:     .word   Undef_Handler
+SWI_Addr:       .word   SWI_Handler
+PAbt_Addr:      .word   PAbt_Handler
+DAbt_Addr:      .word   DAbt_Handler
+                .word   0                      /* Reserved Address */
+IRQ_Addr:       .word   irq_handler_resolver
+FIQ_Addr:       .word   FIQ_Handler
+
+Undef_Handler:  B       Undef_Handler
+SWI_Handler:    B       SWI_Handler
+PAbt_Handler:   B       PAbt_Handler
+DAbt_Handler:   B       DAbt_Handler
+FIQ_Handler:    B       FIQ_Handler
+
+        .end
diff --git a/embedded/arch/arm/mach-lpc21xx/libs/hal/startup.S b/embedded/arch/arm/mach-lpc21xx/libs/hal/startup.S
new file mode 100644 (file)
index 0000000..3201fbc
--- /dev/null
@@ -0,0 +1,128 @@
+#/***********************************************************************/
+#/*  Startup file for LPC21xx MCU applications                          */
+#/*  Partially inspired by KEIL ELEKTRONIK startup code                 */
+#/***********************************************************************/
+
+
+# *** Startup Code (executed after Reset) ***
+
+# Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs
+        .set  MODE_USR, 0x10            // User Mode
+        .set  MODE_FIQ, 0x11            // FIQ Mode
+        .set  MODE_IRQ, 0x12            // IRQ Mode
+        .set  MODE_SVC, 0x13            // Supervisor Mode
+        .set  MODE_ABT, 0x17            // Abort Mode
+        .set  MODE_UND, 0x1B            // Undefined Mode
+        .set  MODE_SYS, 0x1F            // System Mode
+
+        .equ  I_BIT, 0x80               // when I bit is set, IRQ is disabled
+        .equ  F_BIT, 0x40               // when F bit is set, FIQ is disabled
+
+        .set  UND_STACK_SIZE, 0x00000004
+        .set  ABT_STACK_SIZE, 0x00000004
+        .set  FIQ_STACK_SIZE, 0x00000004
+        .set  IRQ_STACK_SIZE, 0X00000400
+        .set  SVC_STACK_SIZE, 0x00000004
+
+# Starupt Code must be linked first at Address at which it expects to run.
+
+        .text
+#       .arm
+
+        .global _stack                  // top of stack
+        .global _startup
+       .global  reset_handler
+        .func   _startup
+_startup:
+
+reset_handler:  
+
+# Memory Mapping (when Interrupt Vectors are in RAM)
+        .equ    MEMMAP, 0xE01FC040  /* Memory Mapping Control */
+
+        MOV     R1, #1
+        LDR     R0, =hal_vectors
+       CMP     R0, #0
+       BEQ     mam_sram
+        MOV     R1, #2
+mam_sram:
+        LDR     R0, =MEMMAP
+        STR     R1, [R0]
+
+# Initialize Interrupt System
+# - Set stack location for each mode
+# - Leave in System Mode with Interrupts Disabled
+# -----------------------------------------------
+        ldr   r0,=_stack
+        msr   CPSR_c,#MODE_UND|I_BIT|F_BIT // Undefined Instruction Mode
+        mov   sp,r0
+        sub   r0,r0,#UND_STACK_SIZE
+        msr   CPSR_c,#MODE_ABT|I_BIT|F_BIT // Abort Mode
+        mov   sp,r0
+        sub   r0,r0,#ABT_STACK_SIZE
+        msr   CPSR_c,#MODE_FIQ|I_BIT|F_BIT // FIQ Mode
+        mov   sp,r0
+        sub   r0,r0,#FIQ_STACK_SIZE
+        msr   CPSR_c,#MODE_IRQ|I_BIT|F_BIT // IRQ Mode
+        mov   sp,r0
+        sub   r0,r0,#IRQ_STACK_SIZE
+        msr   CPSR_c,#MODE_SVC|I_BIT|F_BIT // Supervisor Mode
+        mov   sp,r0
+        sub   r0,r0,#SVC_STACK_SIZE
+        msr   CPSR_c,#MODE_SYS|I_BIT|F_BIT // System Mode
+        mov   sp,r0
+
+# Disable interrupt from VIC
+        .equ    VICINTENABLE,    0xFFFFF010
+        .equ    VICINTENCLR,     0xFFFFF014
+        .equ    VICSOFTINT,      0xFFFFF018
+        .equ    VICSOFTINTCLEAR, 0xFFFFF01C
+        LDR     R0, =VICINTENABLE
+        MOV     R1, #0
+        STR     R1, [R0]
+        MOV     R1, #0xFFFFFFFF
+        STR     R1, [R0,#VICINTENCLR-VICINTENABLE]
+        STR     R1, [R0,#VICSOFTINTCLEAR-VICINTENABLE]
+
+# Enable interrupts and return back into supervisor mode
+        msr   CPSR_c,#MODE_SVC  // Supervisor Mode
+
+# Relocate .data section (Copy from ROM to RAM)
+        LDR     R1, =_etext
+        LDR     R2, =_data
+        LDR     R3, =_edata
+       CMP     R1, R2
+       BEQ     ZI
+LoopRel:CMP     R2, R3
+        LDRLO   R0, [R1], #4
+        STRLO   R0, [R2], #4
+        BLO     LoopRel
+
+ZI:
+# Clear .bss section (Zero init)
+        MOV     R0, #0
+        LDR     R1, =__bss_start__
+        LDR     R2, =__bss_end__
+LoopZI: CMP     R1, R2
+        STRLO   R0, [R1], #4
+        BLO     LoopZI
+
+
+# Enter the C _setup_board code
+       ADR     LR, __main_start
+        LDR     R0, =_setup_board
+       CMP     R0, #0
+       BEQ     __main_start
+        BX      R0
+
+__main_start:   
+       ADR     LR, __main_exit
+        LDR     R0, =main
+        BX      R0
+
+__main_exit:    B       __main_exit
+
+        .size   _start, . - _start
+        .endfunc
+
+        .end
diff --git a/embedded/arch/arm/mach-lpc21xx/libs/iap/Makefile b/embedded/arch/arm/mach-lpc21xx/libs/iap/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/arch/arm/mach-lpc21xx/libs/iap/Makefile.omk b/embedded/arch/arm/mach-lpc21xx/libs/iap/Makefile.omk
new file mode 100644 (file)
index 0000000..b0c47ee
--- /dev/null
@@ -0,0 +1,14 @@
+# -*- makefile -*-
+
+lib_LIBRARIES = lpciap 
+lpciap_SOURCES = iap.c iap_asm.S
+
+include_HEADERS = lpciap.h
+
+ifeq ($(CONFIG_KEYVAL),y)
+lib_LIBRARIES += lpciap_kvpb
+lpciap_kvpb_SOURCES = iap_kvpb.c
+
+include_HEADERS += lpciap_kvpb.h
+
+endif
diff --git a/embedded/arch/arm/mach-lpc21xx/libs/iap/iap.c b/embedded/arch/arm/mach-lpc21xx/libs/iap/iap.c
new file mode 100644 (file)
index 0000000..9403f68
--- /dev/null
@@ -0,0 +1,118 @@
+#include <system_def.h>
+#include <cpu_def.h>
+#include <hal_machperiph.h>
+
+#define CMD_SUCCESS 0
+#define BUSY 11
+
+#define IAP_CMD_PREPARE        50
+#define IAP_CMD_WRITE          51
+#define IAP_CMD_ERASE          52
+#define IAP_CMD_READ_PARTID    54
+
+uint32_t command[5];
+uint32_t result[2];
+
+extern void iap_asm_entry (unsigned int *,unsigned int *);
+#define iap_entry iap_asm_entry
+
+#ifdef INC_LPC210x_H
+inline int addr2sec(unsigned long addr)
+{
+  return addr/0x2000;
+}
+#elif defined INC_LPC214x_H
+inline int addr2sec(unsigned long addr)
+{
+  if (addr<0x8000) return (addr>>12);
+  else if (addr<0x78000) return (addr>>15)+7;
+       else return 22+((addr&0x7fff)>>12); 
+}
+#else
+#error "Undefined type of CPU for function addr2sec!"
+#endif
+
+int lpcisp_read_partid() 
+{
+  command[0] = IAP_CMD_READ_PARTID;
+  iap_entry(command, result);
+  return result[1];
+}
+
+int lpcisp_prepare_sectors(unsigned char start, unsigned char end)
+{
+  command[0] = IAP_CMD_PREPARE;
+  command[1] = start;
+  command[2] = end;
+  command[3] = FOSC/1000;
+
+  iap_entry(command, result);
+
+  return (CMD_SUCCESS == *result);
+}
+
+int lpcisp_erase_sectors(unsigned char start, unsigned char end)
+{
+  command[0] = IAP_CMD_ERASE;
+  command[1] = start;
+  command[2] = end;
+  command[3] = FOSC/1000;
+
+  iap_entry(command, result);
+
+  return (CMD_SUCCESS == *result);
+}
+
+int lpcisp_erase(void *addr, int len)
+{
+  int start,end;
+  unsigned long flags;
+  
+  start=addr2sec((unsigned long)addr);
+  end=addr2sec((unsigned long)addr+len-1);
+  
+  if (end<start) return 0;
+
+  save_and_cli(flags);
+  lpc_pll_off();
+
+  lpcisp_prepare_sectors(start,end);
+  if (CMD_SUCCESS != *result) return 0;
+
+  lpcisp_erase_sectors(start,end);
+
+  lpc_pll_on();
+  restore_flags(flags);
+
+  return (CMD_SUCCESS == *result);
+}
+
+int lpcisp_write(void *addr_des, const void *addr_src, int len)
+{
+  int start,end;
+  unsigned long flags;
+  
+  start=addr2sec((unsigned long)addr_des);
+  end=start;
+
+  save_and_cli(flags);
+  lpc_pll_off();
+
+  lpcisp_prepare_sectors(start,end);
+  if (CMD_SUCCESS != *result) return 0;
+
+  command[0] = IAP_CMD_WRITE;
+  command[1] = (unsigned int)addr_des;
+  command[2] = (unsigned int)addr_src;
+  command[3] = len;
+  command[4] = FOSC/1000;
+
+  iap_entry(command, result);
+
+  lpc_pll_on();
+  restore_flags(flags);
+
+  return (CMD_SUCCESS == *result);
+}
+
+
diff --git a/embedded/arch/arm/mach-lpc21xx/libs/iap/iap_asm.S b/embedded/arch/arm/mach-lpc21xx/libs/iap/iap_asm.S
new file mode 100644 (file)
index 0000000..8867e32
--- /dev/null
@@ -0,0 +1,13 @@
+.global iap_asm_entry
+.func iap_asm_entry
+iap_asm_entry:
+       stmfd   sp!,{r1, r2, lr}
+       adr     lr,iap_asm_exit
+       ldr     r2,=0x7FFFFFF1
+       bx      r2
+
+iap_asm_exit:
+       ldmfd   sp!,{r1, r2, lr}
+       mov     pc,lr
+.endfunc
+.end
diff --git a/embedded/arch/arm/mach-lpc21xx/libs/iap/iap_kvpb.c b/embedded/arch/arm/mach-lpc21xx/libs/iap/iap_kvpb.c
new file mode 100644 (file)
index 0000000..268ec9e
--- /dev/null
@@ -0,0 +1,50 @@
+#include <string.h>
+#include <keyvalpb.h>
+#include <lpciap.h>
+
+unsigned long lpciap_buff[ISP_RAM2FLASH_BLOCK_SIZE/4];
+char *lpciap_addr_base=NULL;
+
+#define ISP_RAM2FLASH_BLOCK_SIZE_MASK (ISP_RAM2FLASH_BLOCK_SIZE-1)
+
+int lpcisp_kvpb_erase(struct kvpb_block *store, void *base,int size)
+{
+  return lpcisp_erase(base, size);
+}
+
+int lpcisp_kvpb_flush(struct kvpb_block *store) 
+{
+  if (lpciap_addr_base==NULL) return -1;
+  lpcisp_write(lpciap_addr_base,lpciap_buff,ISP_RAM2FLASH_BLOCK_SIZE);
+  lpciap_addr_base=NULL;
+  return 0;
+}
+
+int lpcisp_kvpb_copy(struct kvpb_block *store,void *des, const void *src, int len)
+{
+  char *addr_base,*addr_src=(char*)src;
+  int cp_len;
+
+  while(len) {
+    addr_base=(char*)((unsigned long)des&~ISP_RAM2FLASH_BLOCK_SIZE_MASK);
+    cp_len=ISP_RAM2FLASH_BLOCK_SIZE-((unsigned long)des&ISP_RAM2FLASH_BLOCK_SIZE_MASK);
+    if (len<cp_len) cp_len=len;
+    if (lpciap_addr_base) {
+      if (lpciap_addr_base!=addr_base) {
+        lpcisp_kvpb_flush(store);
+        memcpy(lpciap_buff,addr_base,ISP_RAM2FLASH_BLOCK_SIZE);
+        lpciap_addr_base=addr_base;
+      }
+    } else {
+      memcpy(lpciap_buff,addr_base,ISP_RAM2FLASH_BLOCK_SIZE);
+      lpciap_addr_base=addr_base;
+    }
+    memcpy((char*)lpciap_buff+((unsigned long)des&ISP_RAM2FLASH_BLOCK_SIZE_MASK),addr_src,cp_len);
+    des=(char*)des+cp_len;
+    addr_src+=cp_len;
+    len-=cp_len;
+    if (((unsigned long)des&ISP_RAM2FLASH_BLOCK_SIZE_MASK)==0x00) 
+      lpcisp_kvpb_flush(store);
+  }
+  return 1;
+}
diff --git a/embedded/arch/arm/mach-lpc21xx/libs/iap/lpciap.h b/embedded/arch/arm/mach-lpc21xx/libs/iap/lpciap.h
new file mode 100644 (file)
index 0000000..5a8af6e
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _LPCIAP_H
+#define _LPCIAP_H
+
+int lpcisp_read_partid();
+int lpcisp_erase(void *addr, int len);
+int lpcisp_write(void *addr_des, const void *addr_src, int len);
+
+#endif  /* _LPCIAP_H */
diff --git a/embedded/arch/arm/mach-lpc21xx/libs/iap/lpciap_kvpb.h b/embedded/arch/arm/mach-lpc21xx/libs/iap/lpciap_kvpb.h
new file mode 100644 (file)
index 0000000..3057ab9
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _LPCIAP_KVPB_H
+#define _LPCIAP_KVPB_H
+
+#include <system_def.h>
+
+extern unsigned long lpciap_buff[ISP_RAM2FLASH_BLOCK_SIZE/4];
+
+int lpcisp_kvpb_erase(struct kvpb_block *store, void *base,int size);
+int lpcisp_kvpb_flush(struct kvpb_block *store); 
+int lpcisp_kvpb_copy(struct kvpb_block *store,void *des, const void *src, int len);
+
+#endif  /* _LPCIAP_KVPB_ */
diff --git a/embedded/arch/generic/Makefile b/embedded/arch/generic/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/arch/generic/Makefile.omk b/embedded/arch/generic/Makefile.omk
new file mode 100644 (file)
index 0000000..4291134
--- /dev/null
@@ -0,0 +1,3 @@
+# -*- makefile -*-
+
+SUBDIRS = defines
\ No newline at end of file
diff --git a/embedded/arch/generic/defines/Makefile b/embedded/arch/generic/defines/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/arch/generic/defines/Makefile.omk b/embedded/arch/generic/defines/Makefile.omk
new file mode 100644 (file)
index 0000000..5bbf0f6
--- /dev/null
@@ -0,0 +1,4 @@
+# -*- makefile -*-
+
+include_HEADERS +=  byteswap.h endian.h lt_timer.h lt_timer_types.h
+#include_HEADERS = $(notdir $(wildcard $(SOURCES_DIR)/*.h)) 
diff --git a/embedded/arch/generic/defines/byteswap.h b/embedded/arch/generic/defines/byteswap.h
new file mode 100644 (file)
index 0000000..2324696
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef _BYTESWAP_H
+#define _BYTESWAP_H    1
+
+#if defined(__KEIL__)
+#define __bswap_16(x) ( (((x) << 8) & 0xFF00) | (((x) >> 8) & 0x00FF) )
+#else
+#define __bswap_16(x) ({unsigned short __x=(x); \
+                       (((__x>>8)&0xff)|((__x&0xff)<<8)); })
+#endif
+
+#if defined(__KEIL__)
+    //todo
+#else
+#define __bswap_32(x) ({unsigned long __y=(x); \
+                       (__bswap_16(__y>>16)|__bswap_16(__y)<<16); })
+#endif
+
+#define bswap_16(x) __bswap_16 (x)
+
+#define bswap_32(x) __bswap_32 (x)
+
+#endif /* byteswap.h */
diff --git a/embedded/arch/generic/defines/endian.h b/embedded/arch/generic/defines/endian.h
new file mode 100644 (file)
index 0000000..13d6d51
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef        _ENDIAN_H
+#define        _ENDIAN_H       1
+
+#define        __LITTLE_ENDIAN 1234
+#define        __BIG_ENDIAN    4321
+#define        __PDP_ENDIAN    3412
+
+#if defined(__i386__) || defined(SDCC) || defined (__ARMEL__)
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#endif
+
+#if defined(__H8300__) || defined(__H8500__) || defined (__H8300H__) ||  defined(__W65__) || defined (__H8300S__) || defined (__m68k__) || defined (__ARMEB__) || defined(__KEIL__)
+#define __BYTE_ORDER __BIG_ENDIAN
+#endif
+
+#endif /* endian.h */
diff --git a/embedded/arch/generic/defines/lt_timer.h b/embedded/arch/generic/defines/lt_timer.h
new file mode 100644 (file)
index 0000000..772cf13
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef _LT_TIMER_H
+#define _LT_TIMER_H
+
+#include <types.h>
+#include <system_def.h>
+#include <cpu_def.h>
+#include <lt_timer_types.h>
+
+//timers
+
+#ifndef LT_TIMER_VAR_LOC
+#define LT_TIMER_VAR_LOC
+#endif
+
+static lt_ticks_t LT_TIMER_VAR_LOC last_ticks;
+static lt_mstime_t LT_TIMER_VAR_LOC actual_msec; 
+
+/* Declaration of ulan light timers */
+
+#define lt_get_msbase()     (1000/SYS_TIMER_HZ)                /* in ms */
+#define lt_get_ticks()      (get_sys_timer_ticks())
+
+static inline void
+lt_mstime_update()
+{
+  lt_ticks_t LT_TIMER_VAR_LOC act_ticks;
+  lt_mstime_t LT_TIMER_VAR_LOC msec_diff;
+
+  act_ticks=lt_get_ticks();
+  msec_diff=((lt_tidiff_t)(act_ticks-last_ticks))*lt_get_msbase();
+  last_ticks=act_ticks;
+
+  actual_msec+=msec_diff;
+}
+
+
+#define LT_TIMER_DEC(cust_prefix) \
+\
+extern lt_mstime_t LT_TIMER_VAR_LOC cust_prefix##_last_expired; \
+static inline void \
+cust_prefix##_init() \
+{\
+  lt_mstime_update();\
+  cust_prefix##_last_expired=actual_msec;\
+}\
+static inline int \
+cust_prefix##_expired(lt_mstime_t expiration) \
+{\
+  lt_mstime_update();\
+  \
+  if ((lt_msdiff_t)(actual_msec-cust_prefix##_last_expired)>=expiration) {\
+    cust_prefix##_last_expired=actual_msec;\
+    return 1;\
+  }\
+  \
+  return 0;\
+}
+
+#define LT_TIMER_IMP(cust_prefix) \
+\
+lt_mstime_t LT_TIMER_VAR_LOC cust_prefix##_last_expired; \
+
+
+#endif /* _LT_TIMER_H */
diff --git a/embedded/arch/generic/defines/lt_timer_types.h b/embedded/arch/generic/defines/lt_timer_types.h
new file mode 100644 (file)
index 0000000..e7dc27c
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef _LT_TIMER_TYPES_H
+#define _LT_TIMER_TYPES_H
+
+//timers
+
+#ifdef SDCC
+typedef unsigned char lt_ticks_t;
+typedef char lt_tidiff_t;
+typedef unsigned int lt_mstime_t;
+typedef int lt_msdiff_t;
+#define LT_TIMER_VAR_LOC DATA
+#else
+typedef unsigned int lt_ticks_t;
+typedef int lt_tidiff_t;
+typedef unsigned long lt_mstime_t;
+typedef signed long lt_msdiff_t;
+#endif
+
+#endif /* _LT_TIMER_TYPES_H */
diff --git a/embedded/board/Makefile b/embedded/board/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/board/Makefile.omk b/embedded/board/Makefile.omk
new file mode 100644 (file)
index 0000000..ae8ebdc
--- /dev/null
@@ -0,0 +1,3 @@
+# -*- makefile -*-
+
+SUBDIRS = $(ARCH)
diff --git a/embedded/board/arm/Makefile b/embedded/board/arm/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/board/arm/Makefile.omk b/embedded/board/arm/Makefile.omk
new file mode 100644 (file)
index 0000000..2ca7db1
--- /dev/null
@@ -0,0 +1,5 @@
+# -*- makefile -*-
+
+ifneq ($(wildcard $(SOURCES_DIR)/$(BOARD)),)
+SUBDIRS = $(BOARD)
+endif
\ No newline at end of file
diff --git a/embedded/board/arm/ul_usb1/Makefile b/embedded/board/arm/ul_usb1/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/board/arm/ul_usb1/Makefile.omk b/embedded/board/arm/ul_usb1/Makefile.omk
new file mode 100644 (file)
index 0000000..dba8475
--- /dev/null
@@ -0,0 +1,3 @@
+# -*- makefile -*-
+
+SUBDIRS = defines libs
diff --git a/embedded/board/arm/ul_usb1/config/config.bell-keypad b/embedded/board/arm/ul_usb1/config/config.bell-keypad
new file mode 100644 (file)
index 0000000..65b5279
--- /dev/null
@@ -0,0 +1,51 @@
+# -*- makefile -*-
+
+ARCH=arm
+MACH=lpc21xx
+BOARD=ul_usb1
+CONFIG_BOARD_VARIANT=hisc-keypad
+
+CONFIG_APP_HISC_BELL_KEYPAD=y
+CONFIG_OC_UL_DRV_SYSLESS=y
+CONFIG_OC_UL_DRV_U450_TMELATE=y
+CONFIG_ULAN_DY=y
+CONFIG_ULOI_LT=y
+CONFIG_KEYVAL=y
+CONFIG_KBD=y
+
+#CONFIG_STDIO_COM_PORT=0
+
+CROSS_COMPILE = arm-elf-
+TARGET_ARCH = -mcpu=arm7tdmi 
+
+# Set default C flags. If theese are set elsewhere (e.g. on a command
+# line), these default flags are not used.
+DEBUG ?= -g
+OPTIMIZE ?= -O2
+
+LPC_BAUD = 38400
+TOLPC = tolpc --baud $(LPC_BAUD) --sdev /dev/ttyS0
+LOAD_CMD-ramisp = $(TOLPC)  -v -q 7372 -L -f 
+LOAD_CMD-boot = lpc21isp -bin /dev/ttyS0 $(LPC_BAUD) 12000
+
+# This selects linker script
+LD_SCRIPT=lpc2148
+#DEFAULT_LD_SCRIPT_VARIANT=boot
+
+#OUTPUT_FORMATS = bin hex srec
+
+OUTPUT_FORMATS = bin
+
+PROG_BASE=0x20000
+PROG_SIZE=0x20000
+
+UL_SENDHEX ?= ul_sendhex
+MOD ?= 62
+
+LOAD_CMD-app = \
+    $(UL_SENDHEX) -m $(MOD) -r -o 0 ; \
+    $(UL_SENDHEX) -m $(MOD) -o 0 -t 0x101 -s $(PROG_BASE) -l $(PROG_SIZE) -e; \
+    $(UL_SENDHEX) -m $(MOD) -o 0 -t 0x101 -b 256 -s $(PROG_BASE) -f binary
+
+RUN_CMD-app = \
+    $(UL_SENDHEX) -m $(MOD) -r
diff --git a/embedded/board/arm/ul_usb1/config/config.garage-gate b/embedded/board/arm/ul_usb1/config/config.garage-gate
new file mode 100644 (file)
index 0000000..2949391
--- /dev/null
@@ -0,0 +1,50 @@
+# -*- makefile -*-
+
+ARCH=arm
+MACH=lpc21xx
+BOARD=ul_usb1
+CONFIG_BOARD_VARIANT=hisc-garage-gate
+
+CONFIG_APP_HISC_GARAGE_GATE=y
+CONFIG_OC_UL_DRV_SYSLESS=y
+CONFIG_OC_UL_DRV_U450_TMELATE=y
+CONFIG_ULAN_DY=y
+CONFIG_ULOI_LT=y
+CONFIG_KEYVAL=y
+
+#CONFIG_STDIO_COM_PORT=0
+
+CROSS_COMPILE = arm-elf-
+TARGET_ARCH = -mcpu=arm7tdmi 
+
+# Set default C flags. If theese are set elsewhere (e.g. on a command
+# line), these default flags are not used.
+DEBUG ?= -g
+OPTIMIZE ?= -O2
+
+LPC_BAUD = 38400
+TOLPC = tolpc --baud $(LPC_BAUD) --sdev /dev/ttyS0
+LOAD_CMD-ramisp = $(TOLPC)  -v -q 7372 -L -f 
+LOAD_CMD-boot = lpc21isp -bin /dev/ttyS0 $(LPC_BAUD) 12000
+
+# This selects linker script
+LD_SCRIPT=lpc2148
+#DEFAULT_LD_SCRIPT_VARIANT=boot
+
+#OUTPUT_FORMATS = bin hex srec
+
+OUTPUT_FORMATS = bin
+
+PROG_BASE=0x20000
+PROG_SIZE=0x20000
+
+UL_SENDHEX ?= ul_sendhex
+MOD ?= 62
+
+LOAD_CMD-app = \
+    $(UL_SENDHEX) -m $(MOD) -r -o 0 ; \
+    $(UL_SENDHEX) -m $(MOD) -o 0 -t 0x101 -s $(PROG_BASE) -l $(PROG_SIZE) -e; \
+    $(UL_SENDHEX) -m $(MOD) -o 0 -t 0x101 -b 256 -s $(PROG_BASE) -f binary
+
+RUN_CMD-app = \
+    $(UL_SENDHEX) -m $(MOD) -r
diff --git a/embedded/board/arm/ul_usb1/config/config.ha-switch b/embedded/board/arm/ul_usb1/config/config.ha-switch
new file mode 100644 (file)
index 0000000..4ed1f04
--- /dev/null
@@ -0,0 +1,48 @@
+# -*- makefile -*-
+
+ARCH=arm
+MACH=lpc21xx
+BOARD=ul_usb1
+CONFIG_BOARD_VARIANT=ha-switch
+
+CONFIG_HA_LIGHT_SWITCH=y
+
+CONFIG_OC_UL_DRV_SYSLESS=y
+CONFIG_OC_UL_DRV_U450_VARPINS=y
+CONFIG_OC_UL_DRV_U450_VARPINS_DIRNEG=y
+CONFIG_OC_UL_DRV_U450_LOOPBACK=y
+CONFIG_ULAN_DY=y
+CONFIG_ULOI_LT=y
+CONFIG_KEYVAL=y
+
+# CONFIG_STDIO_COM_PORT=0
+
+CROSS_COMPILE = arm-elf-
+TARGET_ARCH = -mcpu=arm7tdmi 
+
+# Set default C flags. If theese are set elsewhere (e.g. on a command
+# line), these default flags are not used.
+DEBUG ?= -g
+OPTIMIZE ?= -O2
+
+# This selects linker script
+LD_SCRIPT=lpc2105
+#DEFAULT_LD_SCRIPT_VARIANT=boot
+
+#OUTPUT_FORMATS = bin hex srec
+
+OUTPUT_FORMATS = bin
+
+PROG_BASE=0xA000
+PROG_SIZE=0x10000
+
+UL_SENDHEX ?= ul_sendhex
+MOD ?= 62
+
+LOAD_CMD-app = \
+    $(UL_SENDHEX) -m $(MOD) -r -o 0 ; \
+    $(UL_SENDHEX) -m $(MOD) -o 0 -t 0x101 -s $(PROG_BASE) -l $(PROG_SIZE) -e; \
+    $(UL_SENDHEX) -m $(MOD) -o 0 -t 0x101 -b 512 -s $(PROG_BASE) -f binary
+
+RUN_CMD-app = \
+    $(UL_SENDHEX) -m $(MOD) -r
diff --git a/embedded/board/arm/ul_usb1/config/config.ha-switch-ulboot b/embedded/board/arm/ul_usb1/config/config.ha-switch-ulboot
new file mode 100644 (file)
index 0000000..bda5aa0
--- /dev/null
@@ -0,0 +1,41 @@
+# -*- makefile -*-
+
+ARCH=arm
+MACH=lpc21xx
+BOARD=ul_usb1
+CONFIG_BOARD_VARIANT=ha-switch
+
+CONFIG_ULBOOT=y
+
+CONFIG_OC_UL_DRV_SYSLESS=y
+CONFIG_OC_UL_DRV_U450_VARPINS=y
+CONFIG_OC_UL_DRV_U450_VARPINS_DIRNEG=y
+CONFIG_OC_UL_DRV_U450_LOOPBACK=y
+CONFIG_KEYVAL=y
+CONFIG_ULAN_DY=y
+
+# CONFIG_STDIO_COM_PORT=0
+
+CROSS_COMPILE = arm-elf-
+TARGET_ARCH = -mcpu=arm7tdmi 
+
+# Set default C flags. If theese are set elsewhere (e.g. on a command
+# line), these default flags are not used.
+DEBUG ?= -g
+OPTIMIZE ?= -O2
+
+# This selects linker script
+LD_SCRIPT=lpc2105
+#DEFAULT_LD_SCRIPT_VARIANT=boot
+
+#OUTPUT_FORMATS = bin hex srec
+
+OUTPUT_FORMATS = hex bin
+
+TOHIT=lpc21isp
+DEV=/dev/ttyUSB0
+CPU_SYS_KHZ=14745
+BAUD=57600
+
+LOAD_CMD-boot = \
+    $(TOHIT) $(DEV) $(BAUD) $(CPU_SYS_KHZ)
diff --git a/embedded/board/arm/ul_usb1/config/config.u2uv2 b/embedded/board/arm/ul_usb1/config/config.u2uv2
new file mode 100644 (file)
index 0000000..6deb39e
--- /dev/null
@@ -0,0 +1,58 @@
+# -*- makefile -*-
+
+ARCH=arm
+MACH=lpc21xx
+BOARD=ul_usb1
+
+CONFIG_OC_UL_DRV_SYSLESS=y
+CONFIG_OC_UL_DRV_U450_VARPINS=y
+CONFIG_OC_UL_DRV_U450_VARPINS_MSRSWAP=y
+CONFIG_OC_UL_DRV_U450_TMELATE=y
+#CONFIG_ULAN_DY=y
+#CONFIG_ULOI_LT=y
+#CONFIG_ULOI_GENOBJIDTAG=y
+#CONFIG_KEYVAL=y
+CONFIG_USB_BASE=y
+CONFIG_USB_LPCUSB=y
+CONFIG_APP_U2U_V2=y
+
+#CONFIG_APP_TEST_LPC=y
+#CONFIG_APP_ULAD31=y
+#CONFIG_ULBOOT=y
+
+CONFIG_STDIO_COM_PORT=0
+
+CROSS_COMPILE = arm-elf-
+TARGET_ARCH = -mcpu=arm7tdmi 
+
+# Set default C flags. If theese are set elsewhere (e.g. on a command
+# line), these default flags are not used.
+DEBUG ?= -g
+OPTIMIZE ?= -O2
+
+LPC_BAUD = 38400
+TOLPC = tolpc --baud $(LPC_BAUD) --sdev /dev/ttyS0
+LOAD_CMD-ramisp = $(TOLPC)  -v -q 7372 -L -f 
+LOAD_CMD-boot = lpc21isp -bin /dev/ttyUSB0 $(LPC_BAUD) 12000
+
+# This selects linker script
+LD_SCRIPT=lpc2148
+#DEFAULT_LD_SCRIPT_VARIANT=boot
+
+#OUTPUT_FORMATS = bin hex srec
+
+OUTPUT_FORMATS = bin
+
+PROG_BASE=0x20000
+PROG_SIZE=0x20000
+
+UL_SENDHEX ?= ul_sendhex
+MOD ?= 3
+
+LOAD_CMD-app = \
+    $(UL_SENDHEX) -m $(MOD) -r -o 0 ; \
+    $(UL_SENDHEX) -m $(MOD) -o 0 -t 0x101 -s $(PROG_BASE) -l $(PROG_SIZE) -e; \
+    $(UL_SENDHEX) -m $(MOD) -o 0 -t 0x101 -b 256 -s $(PROG_BASE) -f binary
+
+RUN_CMD-app = \
+    $(UL_SENDHEX) -m $(MOD) -g $(PROG_BASE)
diff --git a/embedded/board/arm/ul_usb1/config/config.ul_usb1 b/embedded/board/arm/ul_usb1/config/config.ul_usb1
new file mode 100644 (file)
index 0000000..e0eccad
--- /dev/null
@@ -0,0 +1,55 @@
+# -*- makefile -*-
+
+ARCH=arm
+MACH=lpc21xx
+BOARD=ul_usb1
+
+#CONFIG_BOARD_VARIANT=aa_rch
+CONFIG_OC_UL_DRV_SYSLESS=y
+CONFIG_OC_UL_DRV_U450_VARPINS=y
+CONFIG_OC_UL_DRV_U450_VARPINS_MSRSWAP=y
+CONFIG_OC_UL_DRV_U450_TMELATE=y
+CONFIG_ULAN_DY=y
+CONFIG_ULOI_LT=y
+CONFIG_ULOI_GENOBJIDTAG=y
+CONFIG_KEYVAL=y
+CONFIG_APP_TEST_LPC=y
+CONFIG_APP_ULAD31=y
+CONFIG_ULBOOT=y
+
+CONFIG_STDIO_COM_PORT=0
+
+CROSS_COMPILE = arm-elf-
+TARGET_ARCH = -mcpu=arm7tdmi 
+
+# Set default C flags. If theese are set elsewhere (e.g. on a command
+# line), these default flags are not used.
+DEBUG ?= -g
+OPTIMIZE ?= -O2
+
+LPC_BAUD = 38400
+TOLPC = tolpc --baud $(LPC_BAUD) --sdev /dev/ttyS0
+LOAD_CMD-ramisp = $(TOLPC)  -v -q 7372 -L -f 
+LOAD_CMD-boot = lpc21isp -bin /dev/ttyS0 $(LPC_BAUD) 12000
+
+# This selects linker script
+LD_SCRIPT=lpc2148
+#DEFAULT_LD_SCRIPT_VARIANT=boot
+
+#OUTPUT_FORMATS = bin hex srec
+
+OUTPUT_FORMATS = bin
+
+PROG_BASE=0x20000
+PROG_SIZE=0x20000
+
+UL_SENDHEX ?= ul_sendhex
+MOD ?= 3
+
+LOAD_CMD-app = \
+    $(UL_SENDHEX) -m $(MOD) -r -o 0 ; \
+    $(UL_SENDHEX) -m $(MOD) -o 0 -t 0x101 -s $(PROG_BASE) -l $(PROG_SIZE) -e; \
+    $(UL_SENDHEX) -m $(MOD) -o 0 -t 0x101 -b 256 -s $(PROG_BASE) -f binary
+
+RUN_CMD-app = \
+    $(UL_SENDHEX) -m $(MOD) -g $(PROG_BASE)
diff --git a/embedded/board/arm/ul_usb1/config/config.ulboot b/embedded/board/arm/ul_usb1/config/config.ulboot
new file mode 100644 (file)
index 0000000..52b0004
--- /dev/null
@@ -0,0 +1,40 @@
+# -*- makefile -*-
+
+ARCH=arm
+MACH=lpc21xx
+BOARD=ul_usb1
+
+CONFIG_ULBOOT=y
+
+CONFIG_OC_UL_DRV_SYSLESS=y
+CONFIG_OC_UL_DRV_U450_VARPINS=y
+CONFIG_OC_UL_DRV_U450_VARPINS_MSRSWAP=y
+CONFIG_OC_UL_DRV_U450_TMELATE=y
+CONFIG_KEYVAL=y
+CONFIG_ULAN_DY=y
+
+# CONFIG_STDIO_COM_PORT=0
+
+CROSS_COMPILE = arm-elf-
+TARGET_ARCH = -mcpu=arm7tdmi 
+
+# Set default C flags. If theese are set elsewhere (e.g. on a command
+# line), these default flags are not used.
+DEBUG ?= -g
+OPTIMIZE ?= -O2
+
+# This selects linker script
+LD_SCRIPT=lpc2148
+#DEFAULT_LD_SCRIPT_VARIANT=boot
+
+#OUTPUT_FORMATS = bin hex srec
+
+OUTPUT_FORMATS = hex bin
+
+TOHIT=lpc21isp
+DEV=/dev/ttyUSB0
+CPU_SYS_KHZ=12000
+BAUD=38400
+
+LOAD_CMD-boot = \
+    $(TOHIT) $(DEV) $(BAUD) $(CPU_SYS_KHZ)
diff --git a/embedded/board/arm/ul_usb1/config/config.usbcan b/embedded/board/arm/ul_usb1/config/config.usbcan
new file mode 100644 (file)
index 0000000..cc5d422
--- /dev/null
@@ -0,0 +1,63 @@
+# -*- makefile -*-
+
+ARCH=arm
+MACH=lpc21xx
+BOARD=ul_usb1
+
+#CONFIG_BOARD_VARIANT=aa_rch
+#CONFIG_OC_UL_DRV_SYSLESS=y
+#CONFIG_OC_UL_DRV_U450_VARPINS=y
+#CONFIG_OC_UL_DRV_U450_VARPINS_MSRSWAP=y
+#CONFIG_ULAN_DY=y
+#CONFIG_ULOI_LT=y
+#CONFIG_ULOI_GENOBJIDTAG=y
+CONFIG_KEYVAL=y
+#CONFIG_APP_TEST_LPC=y
+#CONFIG_APP_ULAD31=y
+#CONFIG_APP_TEST=y
+#CONFIG_APP_USBTEST=y
+#CONFIG_APP_U2U=y
+#CONFIG_APP_U2U_V2=y
+CONFIG_USB_BASE=y
+CONFIG_USB_LPCUSB=y
+CONFIG_APP_USBCAN=y
+#CONFIG_APP_USBBOOT=y
+#CONFIG_ULBOOT=y
+
+
+CONFIG_STDIO_COM_PORT=0
+
+CROSS_COMPILE = arm-elf-
+TARGET_ARCH = -mcpu=arm7tdmi
+
+# Set default C flags. If theese are set elsewhere (e.g. on a command
+# line), these default flags are not used.
+DEBUG ?= -g
+OPTIMIZE ?= -O2
+
+LPC_BAUD = 38400
+TOLPC = tolpc --baud $(LPC_BAUD) --sdev /dev/ttyUSB0
+LOAD_CMD-ramisp = $(TOLPC)  -v -q 7372 -L -f
+LOAD_CMD-boot = lpc21isp -bin /dev/ttyUSB0 $(LPC_BAUD) 12000
+
+# This selects linker script
+LD_SCRIPT=lpc2148
+#DEFAULT_LD_SCRIPT_VARIANT=boot
+
+#OUTPUT_FORMATS = bin hex srec
+
+OUTPUT_FORMATS = bin
+
+PROG_BASE=0x20000
+PROG_SIZE=0x20000
+
+UL_SENDHEX ?= ul_sendhex
+MOD ?= 3
+
+LOAD_CMD-app = \
+    $(UL_SENDHEX) -m $(MOD) -r -o 0 ; \
+    $(UL_SENDHEX) -m $(MOD) -o 0 -t 0x101 -s $(PROG_BASE) -l $(PROG_SIZE) -e; \
+    $(UL_SENDHEX) -m $(MOD) -o 0 -t 0x101 -b 256 -s $(PROG_BASE) -f binary
+
+RUN_CMD-app = \
+    $(UL_SENDHEX) -m $(MOD) -g $(PROG_BASE)
diff --git a/embedded/board/arm/ul_usb1/defines/Makefile b/embedded/board/arm/ul_usb1/defines/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/board/arm/ul_usb1/defines/Makefile.omk b/embedded/board/arm/ul_usb1/defines/Makefile.omk
new file mode 100644 (file)
index 0000000..4ed4e2d
--- /dev/null
@@ -0,0 +1,15 @@
+# -*- makefile -*-
+
+default_CONFIG = CONFIG_BOARD_VARIANT=x
+
+#include_HEADERS = $(notdir $(wildcard $(SOURCES_DIR)/*.h))
+
+ifneq ($(CONFIG_BOARD_VARIANT),)
+
+renamed_include_HEADERS = system_def-$(CONFIG_BOARD_VARIANT).h->system_def.h
+
+else
+
+include_HEADERS = system_def.h
+
+endif # CONFIG_BOARD_VARIANT
diff --git a/embedded/board/arm/ul_usb1/defines/system_def-ha-switch.h b/embedded/board/arm/ul_usb1/defines/system_def-ha-switch.h
new file mode 100644 (file)
index 0000000..80c3ba3
--- /dev/null
@@ -0,0 +1,191 @@
+/*******************************************************************
+  Components for embedded applications builded for
+  laboratory and medical instruments firmware  
+  system_def.h - common cover for definition of hardware adresses,
+                 registers, timing and other hardware dependant
+                parts of embedded hardware
+  Copyright (C) 2001 by Pavel Pisa pisa@cmp.felk.cvut.cz
+            (C) 2002 by PiKRON Ltd. http://www.pikron.com
+
+ *******************************************************************/
+
+#ifndef _SYSTEM_DEF_H_
+#define _SYSTEM_DEF_H_
+
+#include <types.h>
+#include <system_stub.h>
+#include <LPC210x.h>
+#include <bspbase.h>
+
+#ifndef NULL
+#define        NULL    0
+#endif
+
+#define WITH_SFI_SEL
+
+#define VER_CODE(major,minor,patch) (major*0x10000+minor*0x100+patch)
+/* Software version */
+#define SW_VER_ID      "UL_HA_SWITCH"
+#define SW_VER_MAJOR   0
+#define SW_VER_MINOR   2
+#define SW_VER_PATCH   0
+#define SW_VER_CODE    VER_CODE(SW_VER_MAJOR,SW_VER_MINOR,SW_VER_PATCH)
+/* Hardware version */
+#define HW_VER_ID      "UL_HA_SWITCH"
+#define HW_VER_MAJOR   1
+#define HW_VER_MINOR   0
+#define HW_VER_PATCH   0
+#define HW_VER_CODE    VER_CODE(HW_VER_MAJOR,HW_VER_MINOR,HW_VER_PATCH)
+/* Version of mechanical  */
+#define MECH_VER_ID     "UL_HA_SWITCH"
+#define MECH_VER_MAJOR  0
+#define MECH_VER_MINOR  0
+#define MECH_VER_PATCH  0
+#define MECH_VER_CODE  VER_CODE(MECH_VER_MAJOR,MECH_VER_MINOR,MECH_VER_PATCH)
+
+
+// PLL setup values are computed within the LPC include file
+// It relies upon the following defines
+#define FOSC                (14745600)  // Master Oscillator Freq.
+#define PLL_MUL             (4)         // PLL Multiplier
+#define CCLK                (FOSC * PLL_MUL) // CPU Clock Freq.
+
+// Pheripheral Bus Speed Divider
+#define PBSD                1           // MUST BE 1, 2, or 4
+#define PCLK                (CCLK / PBSD) // Pheripheal Bus Clock Freq.
+
+#define SYS_TIMER_HZ       1000
+
+#ifndef BIT
+#define BIT(n)              (1 << (n))
+#endif
+
+// Port Bit Definitions & Macros:    Description - initial conditions
+#define TXD0_BIT            BIT(0)      // used by UART0
+#define RXD0_BIT            BIT(1)      // used by UART0
+#define P0_02_UNUSED_BIT    BIT(2)      // P0.02 unused - low output
+#define OUT2_BIT            BIT(3)      // P0.03 unused - low output
+#define P0_04_UNUSED_BIT    BIT(4)      // P0.04 unused - low output
+#define OUT1_BIT            BIT(5)      // P0.05 unused - low output
+#define IR_BIT              BIT(6)      // P0.06 unused - low output
+#define SPK_P_BIT           BIT(7)      // P0.07 unused - low output
+#define TXD1_BIT            BIT(8)      // used by UART1
+#define RXD1_BIT            BIT(9)      // used by UART1
+#define RTS1_BIT            BIT(10)     // used by UART1
+#define CTS1_BIT            BIT(11)     // used by UART1
+#define DSR1_BIT            BIT(12)     // used by UART1
+#define LED3_BIT            BIT(13)     // used by LED
+#define BOOT_BIT            BIT(14)     // SWITCH
+#define IN1_BIT             BIT(15)     // P0.15 unused - low output
+#define IN2_BIT             BIT(16)     // P0.16 unused - low output
+#define P0_17_UNUSED_BIT    BIT(17)     // P0.17 unused - low output
+#define P0_18_UNUSED_BIT    BIT(18)     // P0.18 unused - low output
+#define LED4_BIT            BIT(19)     // used by LED
+#define LED1_BIT            BIT(20)     // used by LED
+#define LED2_BIT            BIT(21)     // used by LED
+#define USENSE_BIT          BIT(22)     // P0.22 unused - low output
+#define SW1_BIT             BIT(23)     // P0.23 unused - low output
+#define SW3_BIT             BIT(24)     // P0.24 unused - low output
+#define SW2_BIT             BIT(25)     // P0.25 unused - low output
+#define SW4_BIT             BIT(26)     // P0.26 unused - low output
+#define P0_27_UNUSED_BIT    BIT(27)     // P0.27 unused - low output
+#define P0_28_UNUSED_BIT    BIT(28)     // P0.28 unused - low output
+#define P0_29_UNUSED_BIT    BIT(29)     // P0.29 unused - low output
+#define LED5_BIT            BIT(30)     // P0.30 unused - low output
+#define P0_31_UNUSED_BIT    BIT(31)     // P0.31 unused - low output
+
+
+#define P0IO_INPUT_BITS      (uint32_t) ( \
+                                        BOOT_BIT | \
+                                        IR_BIT | \
+                                        IN1_BIT | \
+                                        IN2_BIT | \
+                                        SW1_BIT | \
+                                        SW2_BIT | \
+                                        SW3_BIT | \
+                                        SW4_BIT | \
+                                        UNSENSE_BIT | \
+                                         0 )
+
+#define P0IO_ZERO_BITS       (uint32_t) ( \
+                                         SPK_P_BIT | \
+                                         OUT1_BIT | \
+                                         OUT2_BIT | \
+                                         LED1_BIT | \
+                                         LED2_BIT | \
+                                         LED3_BIT | \
+                                         LED4_BIT | \
+                                         LED5_BIT | \
+                                         P0_02_UNUSED_BIT | \
+                                         P0_04_UNUSED_BIT | \
+                                        P0_17_UNUSED_BIT | \
+                                        P0_18_UNUSED_BIT | \
+                                         P0_27_UNUSED_BIT | \
+                                         P0_28_UNUSED_BIT | \
+                                         P0_29_UNUSED_BIT | \
+                                         P0_31_UNUSED_BIT | \
+                                         0 )
+
+
+
+#define P0IO_ONE_BITS        (uint32_t) ( \
+                                        BOOT_BIT | \
+                                         0 )
+
+#define P0IO_OUTPUT_BITS     (uint32_t) ( \
+                                         P0IO_ZERO_BITS | \
+                                         P0IO_ONE_BITS )
+
+
+/***************************************************************************/
+/* io functions */
+#define LED_GP                 LED1_BIT  /* GENREAL PURPOSE LED */
+#define LED_ERR                        LED2_BIT
+
+/***************************************************************************/
+/* io functions */
+#define IN_PORT                        IO0
+#define OUT_PORT               IO0
+#define LED_PORT               IO0
+
+#define CREATE_PORT_NAME_PIN(port) port##PIN
+#define CREATE_PORT_NAME_CLR(port) port##CLR
+#define CREATE_PORT_NAME_SET(port) port##SET
+
+#define GET_IN_PIN(port,in)    ((CREATE_PORT_NAME_PIN(port) & in)?1:0) 
+#define SET_OUT_PIN(port,out)   (CREATE_PORT_NAME_SET(port)=out)
+#define CLR_OUT_PIN(port,out)   (CREATE_PORT_NAME_CLR(port)=out)
+
+/***************************************************************************/
+/* watchdog */
+//#define WATCHDOG_ENABLED
+#define WATCHDOG_TIMEOUT_MS    1000
+
+/***************************************************************************/
+/* uLan configuration */
+#ifdef UL_LOG_ENABLE
+  #undef UL_LOG_ENABLE
+#endif
+
+#ifdef ULD_DEFAULT_BUFFER_SIZE
+  #undef ULD_DEFAULT_BUFFER_SIZE
+  #define ULD_DEFAULT_BUFFER_SIZE 0x0400
+#endif
+
+#define UL_DRV_SYSLESS_PORT 0xE0010000
+#define UL_DRV_SYSLESS_BAUD 19200
+#define UL_DRV_SYSLESS_IRQ HAL_INTERRUPT_UART1
+#define UL_DRV_SYSLESS_MY_ADR_DEFAULT 1
+
+
+#define watchdog_feed lpc_watchdog_feed
+#define kvpb_erase lpcisp_kvpb_erase
+#define kvpb_copy lpcisp_kvpb_copy
+#define kvpb_flush lpcisp_kvpb_flush
+#define KVPB_DEFAULT_FLAGS KVPB_DESC_DOUBLE|KVPB_DESC_CHUNKWO
+
+#define HAL_ARM_LPC2XXX_EXTINT_ERRATA 
+
+#endif /* _SYSTEM_DEF_H_ */
diff --git a/embedded/board/arm/ul_usb1/defines/system_def-hisc-garage-gate.h b/embedded/board/arm/ul_usb1/defines/system_def-hisc-garage-gate.h
new file mode 100644 (file)
index 0000000..250d27b
--- /dev/null
@@ -0,0 +1,239 @@
+/*******************************************************************
+  Components for embedded applications builded for
+  laboratory and medical instruments firmware  
+  system_def.h - common cover for definition of hardware adresses,
+                 registers, timing and other hardware dependant
+                parts of embedded hardware
+  Copyright (C) 2001 by Pavel Pisa pisa@cmp.felk.cvut.cz
+            (C) 2002 by PiKRON Ltd. http://www.pikron.com
+
+ *******************************************************************/
+
+#ifndef _SYSTEM_DEF_H_
+#define _SYSTEM_DEF_H_
+
+#include <types.h>
+#include <system_stub.h>
+#include <LPC214x.h>
+#include <bspbase.h>
+
+#ifndef NULL
+#define        NULL    0
+#endif
+
+#define WITH_SFI_SEL
+
+#define VER_CODE(major,minor,patch) (major*0x10000+minor*0x100+patch)
+/* Software version */
+#define SW_VER_ID      "UL_USB"
+#define SW_VER_MAJOR   0
+#define SW_VER_MINOR   2
+#define SW_VER_PATCH   0
+#define SW_VER_CODE    VER_CODE(SW_VER_MAJOR,SW_VER_MINOR,SW_VER_PATCH)
+/* Hardware version */
+#define HW_VER_ID      "UL_USB"
+#define HW_VER_MAJOR   1
+#define HW_VER_MINOR   0
+#define HW_VER_PATCH   0
+#define HW_VER_CODE    VER_CODE(HW_VER_MAJOR,HW_VER_MINOR,HW_VER_PATCH)
+/* Version of mechanical  */
+#define MECH_VER_ID     "UL_USB"
+#define MECH_VER_MAJOR  0
+#define MECH_VER_MINOR  0
+#define MECH_VER_PATCH  0
+#define MECH_VER_CODE  VER_CODE(MECH_VER_MAJOR,MECH_VER_MINOR,MECH_VER_PATCH)
+
+
+// PLL setup values are computed within the LPC include file
+// It relies upon the following defines
+#define FOSC                (14745600)  // Master Oscillator Freq.
+#define PLL_MUL             (4)         // PLL Multiplier
+#define CCLK                (FOSC * PLL_MUL) // CPU Clock Freq.
+
+// Pheripheral Bus Speed Divider
+#define PBSD                1           // MUST BE 1, 2, or 4
+#define PCLK                (CCLK / PBSD) // Pheripheal Bus Clock Freq.
+
+#define SYS_TIMER_HZ       1000
+
+#ifndef BIT
+#define BIT(n)              (1 << (n))
+#endif
+
+// Port Bit Definitions & Macros:    Description - initial conditions
+#define TXD0_BIT            BIT(0)      // used by UART0
+#define RXD0_BIT            BIT(1)      // used by UART0
+#define P0_02_UNUSED_BIT    BIT(2)      // P0.02 unused - low output
+#define P0_03_UNUSED_BIT    BIT(3)      // P0.03 unused - low output
+#define P0_04_UNUSED_BIT    BIT(4)      // P0.04 unused - low output
+#define P0_05_UNUSED_BIT    BIT(5)      // P0.05 unused - low output
+#define P0_06_UNUSED_BIT    BIT(6)      // P0.06 unused - low output
+#define P0_07_UNUSED_BIT    BIT(7)      // P0.07 unused - low output
+#define TXD1_BIT            BIT(8)      // used by UART1
+#define RXD1_BIT            BIT(9)      // used by UART1
+#define RTS1_BIT            BIT(10)     // used by UART1
+#define CTS1_BIT            BIT(11)     // used by UART1
+#define DSR1_BIT            BIT(12)     // used by UART1
+#define P0_13_UNUSED_BIT    BIT(13)     // P0.13 unused - low output
+#define BOOT_BIT            BIT(14)     // SWITCH
+#define P0_15_UNUSED_BIT    BIT(15)     // P0.15 unused - low output
+#define P0_16_UNUSED_BIT    BIT(16)     // P0.16 unused - low output
+#define P0_17_UNUSED_BIT    BIT(17)     // P0.17 unused - low output
+#define P0_18_UNUSED_BIT    BIT(18)     // P0.18 unused - low output
+#define P0_19_UNUSED_BIT    BIT(19)     // P0.19 unused - low output
+#define P0_20_UNUSED_BIT    BIT(20)     // P0.20 unused - low output
+#define LED1_BIT            BIT(21)     // used by LED
+#define LED2_BIT            BIT(22)     // used by LED
+#define P0_23_UNUSED_BIT    BIT(23)     // P0.23 unused - low output
+#define P0_24_UNUSED_BIT    BIT(24)     // P0.24 unused - low output
+#define P0_25_UNUSED_BIT    BIT(25)     // P0.25 unused - low output
+#define P0_26_UNUSED_BIT    BIT(26)     // P0.26 unused - low output
+#define P0_27_UNUSED_BIT    BIT(27)     // P0.27 unused - low output
+#define P0_28_UNUSED_BIT    BIT(28)     // P0.28 unused - low output
+#define P0_29_UNUSED_BIT    BIT(29)     // P0.29 unused - low output
+#define P0_30_UNUSED_BIT    BIT(30)     // P0.30 unused - low output
+#define P0_31_UNUSED_BIT    BIT(31)     // P0.31 unused - low output
+
+
+#define P1_16_UNUSED_BIT    BIT(16)     // P1.16 unused - low output
+#define P1_17_UNUSED_BIT    BIT(17)     // P1.17 unused - low output
+#define P1_18_UNUSED_BIT    BIT(18)     // P1.18 unused - low output
+#define P1_19_UNUSED_BIT    BIT(19)     // P1.19 unused - low output
+#define P1_20_UNUSED_BIT    BIT(20)     // P1.20 unused - low output
+#define P1_21_UNUSED_BIT    BIT(21)     // P1.21 unused - low output
+#define P1_22_UNUSED_BIT    BIT(22)     // P1.22 unused - low output
+#define P1_23_UNUSED_BIT    BIT(23)     // P1.23 unused - low output
+#define P1_24_UNUSED_BIT    BIT(24)     // P1.24 unused - low output
+#define P1_25_UNUSED_BIT    BIT(25)     // P1.25 unused - low output
+#define P1_26_GATE          BIT(26)     // used by JTAG
+#define P1_27_UNUSED_BIT    BIT(27)     // used by JTAG
+#define P1_28_UNUSED_BIT    BIT(28)     // used by JTAG
+#define P1_29_UNUSED_BIT    BIT(29)     // used by JTAG
+#define P1_30_UNUSED_BIT    BIT(30)     // used by JTAG
+#define P1_31_UNUSED_BIT    BIT(31)     // used by JTAG
+
+#define P0IO_INPUT_BITS      (uint32_t) ( \
+                                        BOOT_BIT | \
+                                         0 )
+
+#define P1IO_INPUT_BITS      (uint32_t) ( \
+                                         0 )
+
+#define P0IO_ZERO_BITS       (uint32_t) ( \
+                                         P0_02_UNUSED_BIT | \
+                                         P0_03_UNUSED_BIT | \
+                                         P0_04_UNUSED_BIT | \
+                                         P0_05_UNUSED_BIT | \
+                                         P0_06_UNUSED_BIT | \
+                                         P0_07_UNUSED_BIT | \
+                                        P0_13_UNUSED_BIT | \
+                                        P0_15_UNUSED_BIT | \
+                                        P0_16_UNUSED_BIT | \
+                                        P0_17_UNUSED_BIT | \
+                                        P0_18_UNUSED_BIT | \
+                                        P0_19_UNUSED_BIT | \
+                                        P0_20_UNUSED_BIT | \
+                                         P0_23_UNUSED_BIT | \
+                                         P0_24_UNUSED_BIT | \
+                                         P0_25_UNUSED_BIT | \
+                                         P0_26_UNUSED_BIT | \
+                                         P0_27_UNUSED_BIT | \
+                                         P0_28_UNUSED_BIT | \
+                                         P0_29_UNUSED_BIT | \
+                                         P0_30_UNUSED_BIT | \
+                                         P0_31_UNUSED_BIT | \
+                                         0 )
+
+#define P1IO_ZERO_BITS       (uint32_t) ( \
+                                        P1_16_UNUSED_BIT | \
+                                        P1_17_UNUSED_BIT | \
+                                        P1_18_UNUSED_BIT | \
+                                        P1_19_UNUSED_BIT | \
+                                        P1_20_UNUSED_BIT | \
+                                        P1_21_UNUSED_BIT | \
+                                        P1_22_UNUSED_BIT | \
+                                         P1_23_UNUSED_BIT | \
+                                         P1_24_UNUSED_BIT | \
+                                         P1_25_UNUSED_BIT | \
+                                         P1_27_UNUSED_BIT | \
+                                         P1_28_UNUSED_BIT | \
+                                         P1_29_UNUSED_BIT | \
+                                         P1_30_UNUSED_BIT | \
+                                         P1_31_UNUSED_BIT | \
+                                         0 )
+
+
+#define P0IO_ONE_BITS        (uint32_t) ( \
+                                         LED1_BIT | \
+                                        BOOT_BIT | \
+                                         LED2_BIT | \
+                                         0 )
+
+#define P1IO_ONE_BITS        (uint32_t) ( \
+                                         P1_26_GATE | \
+                                         0 )
+
+#define P0IO_OUTPUT_BITS     (uint32_t) ( \
+                                         P0IO_ZERO_BITS | \
+                                         P0IO_ONE_BITS )
+
+#define P1IO_OUTPUT_BITS     (uint32_t) ( \
+                                         P1IO_ZERO_BITS | \
+                                         P1IO_ONE_BITS )
+
+
+/***************************************************************************/
+/* io functions */
+#define LED_GP                 LED1_BIT  /* GENREAL PURPOSE LED */
+#define LED_ERR                        LED2_BIT
+
+#define LED_YELLOW             LED1_BIT
+#define LED_RED                        LED2_BIT
+
+/***************************************************************************/
+/* io functions */
+#define KBD_PORT               IO1
+#define IN_PORT                        IO0
+#define LED_PORT               IO0
+#define OUT_PORT               IO1
+
+#define CREATE_PORT_NAME_PIN(port) port##PIN
+#define CREATE_PORT_NAME_CLR(port) port##CLR
+#define CREATE_PORT_NAME_SET(port) port##SET
+
+#define GET_IN_PIN(port,in)    ((CREATE_PORT_NAME_PIN(port) & in)?1:0) 
+#define SET_OUT_PIN(port,out)   (CREATE_PORT_NAME_SET(port)=out)
+#define CLR_OUT_PIN(port,out)   (CREATE_PORT_NAME_CLR(port)=out)
+
+/***************************************************************************/
+/* watchdog */
+#define WATCHDOG_ENABLED
+#define WATCHDOG_TIMEOUT_MS    1000
+
+/***************************************************************************/
+/* uLan configuration */
+#ifdef UL_LOG_ENABLE
+  #undef UL_LOG_ENABLE
+#endif
+
+#ifdef ULD_DEFAULT_BUFFER_SIZE
+  #undef ULD_DEFAULT_BUFFER_SIZE
+  #define ULD_DEFAULT_BUFFER_SIZE 0x0800
+#endif
+
+#define UL_DRV_SYSLESS_PORT 0xE0010000
+#define UL_DRV_SYSLESS_BAUD 19200
+#define UL_DRV_SYSLESS_IRQ HAL_INTERRUPT_UART1
+#define UL_DRV_SYSLESS_MY_ADR_DEFAULT 1
+
+#define watchdog_feed lpc_watchdog_feed
+#define kvpb_erase lpcisp_kvpb_erase
+#define kvpb_copy lpcisp_kvpb_copy
+#define kvpb_flush lpcisp_kvpb_flush
+#define KVPB_DEFAULT_FLAGS KVPB_DESC_DOUBLE|KVPB_DESC_CHUNKWO
+
+#define HAL_ARM_LPC2XXX_EXTINT_ERRATA 
+
+#endif /* _SYSTEM_DEF_H_ */
diff --git a/embedded/board/arm/ul_usb1/defines/system_def-hisc-keypad.h b/embedded/board/arm/ul_usb1/defines/system_def-hisc-keypad.h
new file mode 100644 (file)
index 0000000..09a90c5
--- /dev/null
@@ -0,0 +1,276 @@
+/*******************************************************************
+  Components for embedded applications builded for
+  laboratory and medical instruments firmware  
+  system_def.h - common cover for definition of hardware adresses,
+                 registers, timing and other hardware dependant
+                parts of embedded hardware
+  Copyright (C) 2001 by Pavel Pisa pisa@cmp.felk.cvut.cz
+            (C) 2002 by PiKRON Ltd. http://www.pikron.com
+
+ *******************************************************************/
+
+#ifndef _SYSTEM_DEF_H_
+#define _SYSTEM_DEF_H_
+
+#include <types.h>
+#include <system_stub.h>
+#include <LPC214x.h>
+#include <bspbase.h>
+
+#ifndef NULL
+#define        NULL    0
+#endif
+
+#define WITH_SFI_SEL
+
+#define VER_CODE(major,minor,patch) (major*0x10000+minor*0x100+patch)
+/* Software version */
+#define SW_VER_ID      "UL_USB"
+#define SW_VER_MAJOR   0
+#define SW_VER_MINOR   2
+#define SW_VER_PATCH   0
+#define SW_VER_CODE    VER_CODE(SW_VER_MAJOR,SW_VER_MINOR,SW_VER_PATCH)
+/* Hardware version */
+#define HW_VER_ID      "UL_USB"
+#define HW_VER_MAJOR   1
+#define HW_VER_MINOR   0
+#define HW_VER_PATCH   0
+#define HW_VER_CODE    VER_CODE(HW_VER_MAJOR,HW_VER_MINOR,HW_VER_PATCH)
+/* Version of mechanical  */
+#define MECH_VER_ID     "UL_USB"
+#define MECH_VER_MAJOR  0
+#define MECH_VER_MINOR  0
+#define MECH_VER_PATCH  0
+#define MECH_VER_CODE  VER_CODE(MECH_VER_MAJOR,MECH_VER_MINOR,MECH_VER_PATCH)
+
+
+// PLL setup values are computed within the LPC include file
+// It relies upon the following defines
+#define FOSC                (14745600)  // Master Oscillator Freq.
+#define PLL_MUL             (4)         // PLL Multiplier
+#define CCLK                (FOSC * PLL_MUL) // CPU Clock Freq.
+
+// Pheripheral Bus Speed Divider
+#define PBSD                1           // MUST BE 1, 2, or 4
+#define PCLK                (CCLK / PBSD) // Pheripheal Bus Clock Freq.
+
+#define SYS_TIMER_HZ       1000
+
+#ifndef BIT
+#define BIT(n)              (1 << (n))
+#endif
+
+// Port Bit Definitions & Macros:    Description - initial conditions
+#define TXD0_BIT            BIT(0)      // used by UART0
+#define RXD0_BIT            BIT(1)      // used by UART0
+#define P0_02_UNUSED_BIT    BIT(2)      // P0.02 unused - low output
+#define P0_03_UNUSED_BIT    BIT(3)      // P0.03 unused - low output
+#define P0_04_UNUSED_BIT    BIT(4)      // P0.04 unused - low output
+#define P0_05_UNUSED_BIT    BIT(5)      // P0.05 unused - low output
+#define IP1_BIT                    BIT(6)      // P0.06 unused - low output
+#define IP2_BIT            BIT(7)      // P0.07 unused - low output
+#define TXD1_BIT            BIT(8)      // used by UART1
+#define RXD1_BIT            BIT(9)      // used by UART1
+#define RTS1_BIT            BIT(10)     // used by UART1
+#define CTS1_BIT            BIT(11)     // used by UART1
+#define DSR1_BIT            BIT(12)     // used by UART1
+#define P0_13_UNUSED_BIT    BIT(13)     // P0.13 unused - low output
+#define BOOT_BIT            BIT(14)     // SWITCH
+#define P0_15_UNUSED_BIT    BIT(15)     // P0.15 unused - low output
+#define P0_16_UNUSED_BIT    BIT(16)     // P0.16 unused - low output
+#define P0_17_UNUSED_BIT    BIT(17)     // P0.17 unused - low output
+#define P0_18_UNUSED_BIT    BIT(18)     // P0.18 unused - low output
+#define P0_19_UNUSED_BIT    BIT(19)     // P0.19 unused - low output
+#define P0_20_UNUSED_BIT    BIT(20)     // P0.20 unused - low output
+#define LED1_BIT            BIT(21)     // used by LED
+#define LED2_BIT            BIT(22)     // used by LED
+#define P0_23_UNUSED_BIT    BIT(23)     // P0.23 unused - low output
+#define P0_24_UNUSED_BIT    BIT(24)     // P0.24 unused - low output
+#define P0_25_UNUSED_BIT    BIT(25)     // P0.25 unused - low output
+#define P0_26_UNUSED_BIT    BIT(26)     // P0.26 unused - low output
+#define P0_27_UNUSED_BIT    BIT(27)     // P0.27 unused - low output
+#define P0_28_UNUSED_BIT    BIT(28)     // P0.28 unused - low output
+#define P0_29_SOUND         BIT(29)     // P0.29 unused - low output
+#define P0_30_LED_R         BIT(30)     // P0.30 unused - low output
+#define P0_31_LED_G         BIT(31)     // P0.31 unused - low output
+
+
+#define P1_16_RELE          BIT(16)     // P1.16 unused - low output
+#define P1_17_UNUSED_BIT    BIT(17)     // P1.17 unused - low output
+#define P1_18_UNUSED_BIT    BIT(18)     // P1.18 unused - low output
+#define P1_19_UNUSED_BIT    BIT(19)     // P1.19 unused - low output
+#define P1_20_UNUSED_BIT    BIT(20)     // P1.20 unused - low output
+#define P1_21_UNUSED_BIT    BIT(21)     // P1.21 unused - low output
+#define P1_22_UNUSED_BIT    BIT(22)     // P1.22 unused - low output
+#define P1_23_UNUSED_BIT    BIT(23)     // P1.23 unused - low output
+#define P1_24_COL369H       BIT(24)     // P1.24 unused - low output
+#define P1_25_COL2580       BIT(25)     // P1.25 unused - low output
+#define P1_26_COL147S       BIT(26)     // used by JTAG
+#define P1_27_ROW123        BIT(27)     // used by JTAG
+#define P1_28_ROW456        BIT(28)     // used by JTAG
+#define P1_29_ROW789        BIT(29)     // used by JTAG
+#define P1_30_ROWS0H        BIT(30)     // used by JTAG
+#define P1_31_RING          BIT(31)     // used by JTAG
+
+#define P0IO_INPUT_BITS      (uint32_t) ( \
+                                        BOOT_BIT | \
+                                        IP1_BIT | \
+                                        IP2_BIT | \
+                                         0 )
+
+#define P1IO_INPUT_BITS      (uint32_t) ( \
+                                        P1_27_ROW123 | \
+                                        P1_28_ROW456 | \
+                                        P1_29_ROW789 | \
+                                        P1_30_ROWS0H | \
+                                        P1_31_RING | \
+                                         0 )
+
+#define P0IO_ZERO_BITS       (uint32_t) ( \
+                                         P0_02_UNUSED_BIT | \
+                                         P0_03_UNUSED_BIT | \
+                                         P0_04_UNUSED_BIT | \
+                                         P0_05_UNUSED_BIT | \
+                                        P0_13_UNUSED_BIT | \
+                                        P0_15_UNUSED_BIT | \
+                                        P0_16_UNUSED_BIT | \
+                                        P0_17_UNUSED_BIT | \
+                                        P0_18_UNUSED_BIT | \
+                                        P0_19_UNUSED_BIT | \
+                                        P0_20_UNUSED_BIT | \
+                                         P0_23_UNUSED_BIT | \
+                                         P0_24_UNUSED_BIT | \
+                                         P0_25_UNUSED_BIT | \
+                                         P0_26_UNUSED_BIT | \
+                                         P0_27_UNUSED_BIT | \
+                                         P0_28_UNUSED_BIT | \
+                                        P0_29_SOUND | \
+                                         0 )
+
+#define P1IO_ZERO_BITS       (uint32_t) ( \
+                                        P1_16_RELE | \
+                                        P1_17_UNUSED_BIT | \
+                                        P1_18_UNUSED_BIT | \
+                                        P1_19_UNUSED_BIT | \
+                                        P1_20_UNUSED_BIT | \
+                                        P1_21_UNUSED_BIT | \
+                                        P1_22_UNUSED_BIT | \
+                                         P1_23_UNUSED_BIT | \
+                                         0 )
+
+
+#define P0IO_ONE_BITS        (uint32_t) ( \
+                                         LED1_BIT | \
+                                        BOOT_BIT | \
+                                         LED2_BIT | \
+                                        P0_30_LED_R | \
+                                        P0_31_LED_G | \
+                                         0 )
+
+#define P1IO_ONE_BITS        (uint32_t) ( \
+                                        P1_24_COL369H | \
+                                        P1_25_COL2580 | \
+                                        P1_26_COL147S | \
+                                         0 )
+
+#define P0IO_OUTPUT_BITS     (uint32_t) ( \
+                                         P0IO_ZERO_BITS | \
+                                         P0IO_ONE_BITS )
+
+#define P1IO_OUTPUT_BITS     (uint32_t) ( \
+                                         P1IO_ZERO_BITS | \
+                                         P1IO_ONE_BITS )
+
+
+/***************************************************************************/
+/* io functions */
+#define LED_GP                 LED1_BIT  /* GENREAL PURPOSE LED */
+#define LED_ERR                        LED2_BIT
+
+#define LED_YELLOW             LED1_BIT
+#define LED_RED                        LED2_BIT
+#define LED_KEYPAD_RED         P0_30_LED_R
+#define LED_KEYPAD_YELLOW      P0_31_LED_G
+
+/***************************************************************************/
+/* io functions */
+#define KBD_PORT               IO1
+#define IN_PORT                        IO0
+#define LED_PORT               IO0
+#define OUT_PORT               IO1
+
+#define CREATE_PORT_NAME_PIN(port) port##PIN
+#define CREATE_PORT_NAME_CLR(port) port##CLR
+#define CREATE_PORT_NAME_SET(port) port##SET
+
+#define GET_IN_PIN(port,in)    ((CREATE_PORT_NAME_PIN(port) & in)?1:0) 
+#define SET_OUT_PIN(port,out)   (CREATE_PORT_NAME_SET(port)=out)
+#define CLR_OUT_PIN(port,out)   (CREATE_PORT_NAME_CLR(port)=out)
+
+/***************************************************************************/
+/* watchdog */
+#define WATCHDOG_ENABLED
+#define WATCHDOG_TIMEOUT_MS    1000
+
+/***************************************************************************/
+/* uLan configuration */
+#ifdef UL_LOG_ENABLE
+  #undef UL_LOG_ENABLE
+#endif
+
+#ifdef ULD_DEFAULT_BUFFER_SIZE
+  #undef ULD_DEFAULT_BUFFER_SIZE
+  #define ULD_DEFAULT_BUFFER_SIZE 0x0800
+#endif
+
+#define UL_DRV_SYSLESS_PORT 0xE0010000
+#define UL_DRV_SYSLESS_BAUD 19200
+#define UL_DRV_SYSLESS_IRQ HAL_INTERRUPT_UART1
+#define UL_DRV_SYSLESS_MY_ADR_DEFAULT 1
+
+#define watchdog_feed lpc_watchdog_feed
+#define kvpb_erase lpcisp_kvpb_erase
+#define kvpb_copy lpcisp_kvpb_copy
+#define kvpb_flush lpcisp_kvpb_flush
+#define KVPB_DEFAULT_FLAGS KVPB_DESC_DOUBLE|KVPB_DESC_CHUNKWO
+
+#define HAL_ARM_LPC2XXX_EXTINT_ERRATA 
+
+/***************************************************************************/
+/* kbd */
+#define KEY_TIMER sys_timer_ticks
+#define KBDDEVICE void
+
+typedef unsigned short kbd_key_t;
+typedef unsigned int kbd_keymod_t;
+typedef long kbd_interval_t;
+typedef unsigned short kbd_scan_code_t;
+
+#define KEY_DEFAULT_TIMES
+#define KEY_PUSH_T     70
+#define KEY_RELEASE_T  50
+#define KEY_REPFIRST_T 60000
+#define KEY_REPNEXT_T  300
+
+#define KBD_DR _reg_PTD_DR
+#define KBD_SSR IO1PIN
+#define KBD_DDIR _reg_PTD_DDIR
+#define KBD_PUEN _reg_PTD_PUEN
+
+typedef unsigned long kbdisr_lock_level_t;
+#define kbdisr_lock   save_and_cli
+#define        kbdisr_unlock restore_flags
+
+#define KBD_SCAN_CNT  3
+#define KBD_SCAN_BIT0 24
+#define KBD_RET_CNT   5
+#define KBD_RET_BIT0  27
+
+#define KBD_SCAN_MASK (((1<<KBD_SCAN_CNT)-1)<<KBD_SCAN_BIT0)
+#define KBD_RET_MASK  (((1<<KBD_RET_CNT)-1)<<KBD_RET_BIT0)
+
+#define KBD_USE_IO_SETCLR_OPS
+
+#endif /* _SYSTEM_DEF_H_ */
diff --git a/embedded/board/arm/ul_usb1/defines/system_def.h b/embedded/board/arm/ul_usb1/defines/system_def.h
new file mode 100644 (file)
index 0000000..12c6cac
--- /dev/null
@@ -0,0 +1,255 @@
+/*******************************************************************
+  Components for embedded applications builded for
+  laboratory and medical instruments firmware  
+  system_def.h - common cover for definition of hardware adresses,
+                 registers, timing and other hardware dependant
+                parts of embedded hardware
+  Copyright (C) 2001 by Pavel Pisa pisa@cmp.felk.cvut.cz
+            (C) 2002 by PiKRON Ltd. http://www.pikron.com
+
+ *******************************************************************/
+
+#ifndef _SYSTEM_DEF_H_
+#define _SYSTEM_DEF_H_
+
+#include <types.h>
+#include <system_stub.h>
+#include <LPC214x.h>
+#include <bspbase.h>
+
+#ifndef NULL
+#define        NULL    0
+#endif
+
+#define WITH_SFI_SEL
+
+#define VER_CODE(major,minor,patch) (major*0x10000+minor*0x100+patch)
+/* Software version */
+#define SW_VER_ID      "UL_USB"
+#define SW_VER_MAJOR   0
+#define SW_VER_MINOR   2
+#define SW_VER_PATCH   0
+#define SW_VER_CODE    VER_CODE(SW_VER_MAJOR,SW_VER_MINOR,SW_VER_PATCH)
+/* Hardware version */
+#define HW_VER_ID      "UL_USB"
+#define HW_VER_MAJOR   1
+#define HW_VER_MINOR   0
+#define HW_VER_PATCH   0
+#define HW_VER_CODE    VER_CODE(HW_VER_MAJOR,HW_VER_MINOR,HW_VER_PATCH)
+/* Version of mechanical  */
+#define MECH_VER_ID     "UL_USB"
+#define MECH_VER_MAJOR  0
+#define MECH_VER_MINOR  0
+#define MECH_VER_PATCH  0
+#define MECH_VER_CODE  VER_CODE(MECH_VER_MAJOR,MECH_VER_MINOR,MECH_VER_PATCH)
+
+
+// PLL setup values are computed within the LPC include file
+// It relies upon the following defines
+//#define FOSC                (11059200)  // Master Oscillator Freq.
+#define FOSC                (12000000)  // Master Oscillator Freq.
+#define PLL_MUL             (4)         // PLL Multiplier
+#define CCLK                (FOSC * PLL_MUL) // CPU Clock Freq.
+
+// Pheripheral Bus Speed Divider
+#define PBSD                1           // MUST BE 1, 2, or 4
+#define PCLK                (CCLK / PBSD) // Pheripheal Bus Clock Freq.
+
+#define SYS_TIMER_HZ       1000
+
+#ifndef BIT
+#define BIT(n)              (1 << (n))
+#endif
+
+// Port Bit Definitions & Macros:    Description - initial conditions
+#define TXD0_BIT            BIT(0)      // used by UART0
+#define RXD0_BIT            BIT(1)      // used by UART0
+#define P0_SCL0_PIN         BIT(2)      // I2C 0 SCL
+#define P0_SDA0_PIN         BIT(3)      // I2C 0 SDA
+#define P0_SCK0_PIN         BIT(4)      // SPI0 clocks
+#define P0_MISO0_PIN        BIT(5)      // SPI0 master input
+#define P0_MOSI0_PIN        BIT(6)      // SPI0 master output
+#define P0_SSEL0_PIN        BIT(7)      // SPI0 external select/ADS1218 DRDY
+#define TXD1_BIT            BIT(8)      // used by UART1
+#define RXD1_BIT            BIT(9)      // used by UART1
+#define RTS1_BIT            BIT(10)     // used by UART1
+#define CTS1_BIT            BIT(11)     // used by UART1
+#define DSR1_BIT            BIT(12)     // used by UART1
+#define LED2_BIT            BIT(13)     // used by LED
+#define BOOT_BIT            BIT(14)     // SWITCH
+#define LED1_BIT            BIT(15)     // used by LED
+#define P0_SWITCH1_PIN      BIT(16)     // pin connected to the switch 1
+#define P0_SCK1_PIN         BIT(17)     // SPI1 clocks
+#define P0_MISO1_PIN        BIT(18)     // SPI1 master input
+#define P0_MOSI1_PIN        BIT(19)     // SPI1 master output
+#define P0_SSEL1_PIN        BIT(20)     // SPI1 slave select/25VF016 chipselect
+#define P0_21_UNUSED_BIT    BIT(21)     // P0.21 unused - low output
+#define P0_22_UNUSED_BIT    BIT(22)     // P0.22 unused - low output
+#define P0_SJA1000_ALE_PIN  BIT(23)     // SJA1000 ALE
+#define P0_24_UNUSED_BIT    BIT(24)     // P0.24 unused - low output
+#define P0_SJA1000_CS_PIN   BIT(25)     // SJA1000 CS
+#define P0_26_UNUSED_BIT    BIT(26)     // P0.26 unused - low output
+#define P0_27_UNUSED_BIT    BIT(27)     // P0.27 unused - low output
+#define P0_SJA1000_RD_PIN   BIT(28)     // SJA1000 RD
+#define P0_SJA1000_WR_PIN   BIT(29)     // SJA1000 WR
+#define P0_SJA1000_INT_PIN  BIT(30)     // SJA1000 INT
+#define P0_USB_CONNECT_PIN  BIT(31)     // USB Connect Control
+
+#define P1_SJA1000_D0_PIN   BIT(16)     // SJA1000 D0
+#define P1_SJA1000_D1_PIN   BIT(17)     // SJA1000 D1
+#define P1_SJA1000_D2_PIN   BIT(18)     // SJA1000 D2
+#define P1_SJA1000_D3_PIN   BIT(19)     // SJA1000 D3
+#define P1_SJA1000_D4_PIN   BIT(20)     // SJA1000 D4
+#define P1_SJA1000_D5_PIN   BIT(21)     // SJA1000 D5
+#define P1_SJA1000_D6_PIN   BIT(22)     // SJA1000 D6
+#define P1_SJA1000_D7_PIN   BIT(23)     // SJA1000 D7
+#define P1_OUT_PORT_CS_PIN  BIT(24)     // Chip select for 74HC574 chip
+#define P1_SJA1000_RST_PIN  BIT(25)     // SJA1000 RST
+#define P1_26_UNUSED_BIT    BIT(26)     // used by JTAG
+#define P1_27_UNUSED_BIT    BIT(27)     // used by JTAG
+#define P1_28_UNUSED_BIT    BIT(28)     // used by JTAG
+#define P1_29_UNUSED_BIT    BIT(29)     // used by JTAG
+#define P1_30_UNUSED_BIT    BIT(30)     // used by JTAG
+#define P1_31_UNUSED_BIT    BIT(31)     // used by JTAG
+
+#define P1_SJA1000_DATA_PINS   (uint32_t) ( \
+                                         P1_SJA1000_D0_PIN | \
+                                         P1_SJA1000_D1_PIN | \
+                                         P1_SJA1000_D2_PIN | \
+                                         P1_SJA1000_D3_PIN | \
+                                         P1_SJA1000_D4_PIN | \
+                                         P1_SJA1000_D5_PIN | \
+                                         P1_SJA1000_D6_PIN | \
+                                         P1_SJA1000_D7_PIN | \
+                                         0 )
+
+#define P0IO_INPUT_BITS      (uint32_t) ( \
+                                         P0_SCL0_PIN | \
+                                         P0_SDA0_PIN | \
+                                         P0_MISO0_PIN | \
+                                         P0_SSEL0_PIN | \
+                                         P0_MISO1_PIN | \
+                                        BOOT_BIT | \
+                                         P0_SWITCH1_PIN | \
+                                         P0_SJA1000_INT_PIN | \
+                                         0 )
+
+#define P1IO_INPUT_BITS      (uint32_t) ( \
+                                         P1_26_UNUSED_BIT | \
+                                         P1_27_UNUSED_BIT | \
+                                         P1_28_UNUSED_BIT | \
+                                         P1_29_UNUSED_BIT | \
+                                         P1_30_UNUSED_BIT | \
+                                         P1_31_UNUSED_BIT | \
+                                         0 )
+
+#define P0IO_ZERO_BITS       (uint32_t) ( \
+                                         P0_21_UNUSED_BIT | \
+                                         P0_22_UNUSED_BIT | \
+                                         P0_24_UNUSED_BIT | \
+                                         P0_26_UNUSED_BIT | \
+                                         P0_27_UNUSED_BIT | \
+                                         P0_USB_CONNECT_PIN | \
+                                         0 )
+
+#define P1IO_ZERO_BITS       (uint32_t) ( \
+                                         P1_SJA1000_DATA_PINS | \
+                                         P1_SJA1000_RST_PIN | \
+                                         0 )
+
+
+#define P0IO_ONE_BITS        (uint32_t) ( \
+                                         P0_SCK0_PIN | \
+                                         P0_MOSI0_PIN | \
+                                         LED1_BIT | \
+                                        BOOT_BIT | \
+                                         LED2_BIT | \
+                                         P0_SCK1_PIN | \
+                                         P0_MOSI1_PIN | \
+                                         P0_SSEL1_PIN | \
+                                        P0_SJA1000_ALE_PIN | \
+                                         P0_SJA1000_CS_PIN | \
+                                         P0_SJA1000_RD_PIN | \
+                                         P0_SJA1000_WR_PIN | \
+                                         0 )
+
+#define P1IO_ONE_BITS        (uint32_t) ( \
+                                         P1_OUT_PORT_CS_PIN | \
+                                         0 )
+
+#define P0IO_OUTPUT_BITS     (uint32_t) ( \
+                                         P0IO_ZERO_BITS | \
+                                         P0IO_ONE_BITS )
+
+#define P1IO_OUTPUT_BITS     (uint32_t) ( \
+                                         P1IO_ZERO_BITS | \
+                                         P1IO_ONE_BITS )
+
+/***************************************************************************/
+/* io functions */
+#define LED_GP                 LED1_BIT  /* GENREAL PURPOSE LED */
+#define LED_ERR                        LED2_BIT
+
+#define LED_YELLOW             LED1_BIT
+#define LED_RED                        LED2_BIT
+
+/***************************************************************************/
+/* io functions */
+#define IN_PORT                        IO0
+#define LED_PORT               IO0
+#define OUT_PORT               IO1
+
+#define CREATE_PORT_NAME_PIN(port) port##PIN
+#define CREATE_PORT_NAME_CLR(port) port##CLR
+#define CREATE_PORT_NAME_SET(port) port##SET
+
+#define GET_IN_PIN(port,in)    ((CREATE_PORT_NAME_PIN(port) & in)?1:0) 
+#define SET_OUT_PIN(port,out)   (CREATE_PORT_NAME_SET(port)=out)
+#define CLR_OUT_PIN(port,out)   (CREATE_PORT_NAME_CLR(port)=out)
+
+/***************************************************************************/
+/* watchdog */
+//#define WATCHDOG_ENABLED
+#define WATCHDOG_TIMEOUT_MS    1000
+
+/***************************************************************************/
+/* uLan configuration */
+
+#ifdef UL_LOG_ENABLE
+  #undef UL_LOG_ENABLE
+#endif
+
+#ifdef ULD_DEFAULT_BUFFER_SIZE
+  #undef ULD_DEFAULT_BUFFER_SIZE
+  #define ULD_DEFAULT_BUFFER_SIZE 0x0800
+#endif
+
+#define UL_DRV_SYSLESS_PORT 0xE0010000
+#define UL_DRV_SYSLESS_BAUD 19200
+#define UL_DRV_SYSLESS_IRQ HAL_INTERRUPT_UART1
+#define UL_DRV_SYSLESS_MY_ADR_DEFAULT 1
+
+#define watchdog_feed lpc_watchdog_feed
+#define kvpb_erase lpcisp_kvpb_erase
+#define kvpb_copy lpcisp_kvpb_copy
+#define kvpb_flush lpcisp_kvpb_flush
+#define KVPB_DEFAULT_FLAGS KVPB_DESC_DOUBLE|KVPB_DESC_CHUNKWO
+
+/***************************************************************************/
+/* USB configuration */
+#define USB_WITH_UDEV_FNC
+#define USB_EP_NUM          32
+#define USB_MAX_PACKET0     64
+#define USB_MAX_PACKET      8
+#define USB_DMA_EP          0x00000000
+
+/***************************************************************************/
+/* i2c0 configuration */
+#define I2C_DRV_SYSLESS_IRQ HAL_INTERRUPT_I2C0
+#define I2C_DRV_SYSLESS_PORT 0xE001C000
+#define I2C_DRV_SYSLESS_BITRATE 100000
+#define I2C_DRV_SYSLESS_SLADR 0
+
+#endif /* _SYSTEM_DEF_H_ */
diff --git a/embedded/board/arm/ul_usb1/libs/Makefile b/embedded/board/arm/ul_usb1/libs/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/board/arm/ul_usb1/libs/Makefile.omk b/embedded/board/arm/ul_usb1/libs/Makefile.omk
new file mode 100644 (file)
index 0000000..1e281da
--- /dev/null
@@ -0,0 +1,3 @@
+# -*- makefile -*-
+
+SUBDIRS = bspbase ldscripts
diff --git a/embedded/board/arm/ul_usb1/libs/bspbase/Makefile b/embedded/board/arm/ul_usb1/libs/bspbase/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/board/arm/ul_usb1/libs/bspbase/Makefile.omk b/embedded/board/arm/ul_usb1/libs/bspbase/Makefile.omk
new file mode 100644 (file)
index 0000000..72f7977
--- /dev/null
@@ -0,0 +1,28 @@
+# -*- makefile -*-
+
+default_CONFIG += CONFIG_OC_UL_DRV_SYSLESS=x
+default_CONFIG += CONFIG_OC_IC_DRV_SYSLESS=x
+default_CONFIG += CONFIG_KEYVAL=x
+default_CONFIG += CONFIG_STDIO_COM_PORT=x
+default_CONFIG += CONFIG_OC_UL_DRV_U450_VARPINS=x
+default_CONFIG += CONFIG_OC_UL_DRV_U450_VARPINS_MSRSWAP=x
+default_CONFIG += CONFIG_OC_UL_DRV_U450_VARPINS_DIRNEG=x
+default_CONFIG += CONFIG_OC_I2C_DRV_SYSLESS=x
+
+LOCAL_CONFIG_H = local_config.h
+
+INCLUDES += -I .
+
+include_HEADERS =  bspbase.h
+
+lib_LIBRARIES = bspbase
+
+bspbase_SOURCES = bsp0hwinit.c 
+
+ifneq ($(CONFIG_STDIO_COM_PORT),)
+bspbase_SOURCES += uart.c
+endif #CONFIG_STDIO_COM_PORT
+
+ifeq ($(CONFIG_KBD),y) 
+bspbase_SOURCES += kbd_io_hisc.c
+endif #CONFIG_KBD
\ No newline at end of file
diff --git a/embedded/board/arm/ul_usb1/libs/bspbase/bsp0hwinit.c b/embedded/board/arm/ul_usb1/libs/bspbase/bsp0hwinit.c
new file mode 100644 (file)
index 0000000..eceffb4
--- /dev/null
@@ -0,0 +1,345 @@
+#include "local_config.h"
+#include <system_def.h>
+#ifdef CONFIG_KEYVAL
+  #include <keyvalpb.h>
+  #include <lpciap.h>
+  #include <lpciap_kvpb.h>
+#endif /* CONFIG_KEYVAL */
+#ifdef CONFIG_STDIO_COM_PORT
+  #include <uart.h>
+#endif
+#ifdef CONFIG_OC_UL_DRV_SYSLESS
+  #include <ul_lib/ulan.h>
+  #include <string.h>
+  #include <ul_drv_init.h>
+  #include <ul_drv_iac.h>
+  #include <ul_lib/ul_drvdef.h>
+  extern long int uld_jiffies;
+#endif /* CONFIG_OC_UL_DRV_SYSLESS */
+#ifdef CONFIG_OC_I2C_DRV_SYSLESS
+  #include <i2c_drv.h>
+#endif /* CONFIG_OC_I2C_DRV_SYSLESS */
+#include <hal_machperiph.h>
+#include <hal_intr.h>
+
+/* timers */
+volatile lt_ticks_t sys_timer_ticks;
+
+static void sysInit(void) 
+{
+
+  lpc_pll_off();
+  lpc_pll_on();
+
+  // setup & enable the MAM
+  MAMCR = 0;
+  MAMTIM = MAMTIM_CYCLES;
+  MAMCR = MAMCR_FULL;
+
+  // set the peripheral bus speed
+  // value computed from config.h
+  VPBDIV = VPBDIV_VALUE;                // set the peripheral bus clock speed
+
+  // setup the parallel port pin
+  IO0CLR = P0IO_ZERO_BITS;                // clear the ZEROs output
+  IO0SET = P0IO_ONE_BITS;                 // set the ONEs output
+  IO0DIR = P0IO_OUTPUT_BITS;              // set the output bit direction
+
+ #ifdef P1IO_OUTPUT_BITS
+  IO1CLR = P1IO_ZERO_BITS;                // clear the ZEROs output
+  IO1SET = P1IO_ONE_BITS;                 // set the ONEs output
+  IO1DIR = P1IO_OUTPUT_BITS;              // set the output bit direction
+ #endif
+
+  IO0CLR = LED1_BIT;                      // Indicate functional state on the LED1
+}
+
+void timer0_isr(void)
+{   
+  unsigned int ir;
+  ir=T0IR;
+  if (ir&TIR_MR0I) {
+    do {
+      T0MR0+=PCLK/SYS_TIMER_HZ;
+      T0IR=TIR_MR0I;               // Clear match0 interrupt
+     #ifdef CONFIG_OC_UL_DRV_SYSLESS
+      uld_jiffies++;
+     #endif
+      sys_timer_ticks++;
+    } while (((int32_t)(T0MR0-T0TC))<0);
+  }
+}
+
+void timerInit(void)
+{
+  sys_timer_ticks=0;
+
+  HAL_INTERRUPT_ATTACH(HAL_INTERRUPT_TIMER0,timer0_isr,0);
+  HAL_INTERRUPT_UNMASK(HAL_INTERRUPT_TIMER0);
+    
+  T0TC=0;
+  T0MCR=0;
+
+  T0MR0=PCLK/SYS_TIMER_HZ;                           /* ms tics */
+  T0MCR|=TMCR_MR0_I;
+
+  T0TCR = TCR_ENABLE; //Run timer 0
+}
+
+#ifdef CONFIG_STDIO_COM_PORT
+
+int uartcon_write(int file, char * ptr, int len)
+{
+  int cnt;
+  unsigned char ch;
+  for(cnt=0;cnt<len;cnt++,ptr++){
+    ch=*ptr;
+    if(ch==0xa)
+      uart0Putch(0xd);
+    uart0Putch(ch);
+  }
+  return cnt;
+}
+
+void init_system_stub(void) {
+  system_stub_ops.write=uartcon_write;
+}
+
+#endif /* CONFIG_STDIO_COM_PORT */
+
+#ifdef CONFIG_OC_UL_DRV_SYSLESS
+
+extern unsigned uld_debug_flg; /* Left application  set defaults */
+
+#ifndef CONFIG_KEYVAL
+unsigned long lpciap_buff[ISP_RAM2FLASH_BLOCK_SIZE/4];
+#endif /* CONFIG_KEYVAL */
+
+#define UL_MTYPE_START32BIT 0x100
+
+static inline int ul_iac_mem_head_rd(uint8_t *buf, int len,
+                      uint32_t* pmtype, uint32_t* pstart, uint32_t* plen)
+{
+  uint32_t val, mtype;
+  if (len<6) return -1;
+  mtype=*(buf++);       /* memory type */
+  mtype+=*(buf++)<<8;
+  val=*(buf++);           /* start address */
+  val+=*(buf++)<<8;
+  if(mtype&UL_MTYPE_START32BIT){
+    if (len<8) return -1;
+    val+=(uint32_t)*(buf++)<<16;
+    val+=(uint32_t)*(buf++)<<24;
+  }
+  *pstart=val;
+  val=*(buf++);           /* length */
+  val+=*(buf++)<<8;
+  if(mtype&UL_MTYPE_START32BIT){
+    if (len==10) {
+      val+=(uint32_t)*(buf++)<<16;
+      val+=(uint32_t)*(buf++)<<24;
+    }
+  }
+  *plen=val;
+  mtype&=~UL_MTYPE_START32BIT;       /* 32-bit start address */
+  *pmtype=mtype;
+  return 0;
+}
+
+int ul_iac_call_rdm(struct ul_drv *udrv,ul_msginfo *msginfo,char *ibuff,ul_iac_data *data)
+{
+  uint32_t mtype,start,len;
+
+  data->len=0;
+
+  if(ul_iac_mem_head_rd((uint8_t *)ibuff, msginfo->len,&mtype,&start,&len))
+    return UL_IAC_RC_PROC;
+
+  if (mtype==0x00) {
+    data->len=len;
+    data->buff=(unsigned char*)start;
+    return UL_IAC_RC_FREEMSG;
+  }
+  return UL_IAC_RC_PROC;
+}
+
+int ul_iac_call_erm(struct ul_drv *udrv,ul_msginfo *msginfo,char *ibuff,ul_iac_data *data)
+{
+  uint32_t mtype,start,len;
+
+  data->len=0;
+
+  if(ul_iac_mem_head_rd((uint8_t *)ibuff, msginfo->len,&mtype,&start,&len))
+    return UL_IAC_RC_PROC;
+
+ #ifdef CONFIG_KEYVAL
+  if (mtype==0x01) {
+    lpcisp_erase((void*)start,len);
+    data->len=0;
+    return UL_IAC_RC_FREEMSG;
+  }
+ #endif /* CONFIG_KEYVAL */
+  return UL_IAC_RC_PROC;
+}
+
+int ul_iac_call_wrm(struct ul_drv *udrv,ul_msginfo *msginfo,char *ibuff,ul_iac_data *data)
+{
+  uint32_t mtype,start,len;
+
+  data->len=0;
+
+  if(ul_iac_mem_head_rd((uint8_t *)ibuff, msginfo->len,&mtype,&start,&len))
+    return UL_IAC_RC_PROC;
+
+  if (mtype==0x00) {
+    memcpy((void*)start,data->buff,data->len);
+    return UL_IAC_RC_FREEMSG;
+  }
+ #ifdef CONFIG_KEYVAL
+  if (mtype==0x01) {
+    lpcisp_write((char*)start, data->buff, ISP_RAM2FLASH_BLOCK_SIZE);
+    return UL_IAC_RC_FREEMSG;
+  }
+ #endif /* CONFIG_KEYVAL */
+  return UL_IAC_RC_PROC;
+}
+
+
+int ul_iac_call_deb(struct ul_drv *udrv,ul_msginfo *msginfo,char *ibuff,ul_iac_data *data)
+{
+  uint32_t debcmd,mtype,start;
+  uint8_t *p=(uint8_t*)ibuff;
+
+  if (msginfo->len<1) return UL_IAC_RC_PROC;
+  debcmd=*(p++);
+  switch (debcmd) {
+    case 0x10: /* goto */
+      data->len=0;
+      if (msginfo->len<5) return UL_IAC_RC_PROC;
+      mtype=*(p++);
+      mtype+=*(p++)<<8;
+      start=*(p++);
+      start+=*(p++)<<8;
+      if(mtype&UL_MTYPE_START32BIT){
+        mtype&=~UL_MTYPE_START32BIT;
+        if (msginfo->len<7) return UL_IAC_RC_PROC;
+        start+=(uint32_t)*(p++)<<16;
+        start+=(uint32_t)*(p++)<<24;
+      }
+      if (mtype==0x00)
+        ((void (*)())start)();
+    default:break;
+  }
+  return UL_IAC_RC_PROC;
+}
+
+int ul_iac_call_res(struct ul_drv *udrv,ul_msginfo *msginfo,char *ibuff,ul_iac_data *data)
+{
+  uint32_t rescmd,pass;
+  uint8_t *p=(uint8_t*)ibuff;
+
+  if (msginfo->len<1) return UL_IAC_RC_PROC;
+  rescmd=*(p++);
+  switch (rescmd) {
+    case ULRES_CPU: /* CPU */
+      data->len=0;
+      if (msginfo->len<3) return UL_IAC_RC_PROC;
+      pass=*(p++);
+      pass+=*(p++)<<8;
+      if (pass==0xaa55) {
+        MEMMAP=MEMMAP_FLASH;
+        lpc_watchdog_init(1,10); /* 10ms */
+        lpc_watchdog_feed();
+        while(1);
+      }
+    default:break;
+  }
+  return UL_IAC_RC_PROC;
+}
+
+int uLanInit()
+{
+  struct ul_drv *udrv;
+
+  /* set rs485 mode for UART1 */
+  PINSEL0 = (PINSEL0 & ~0xFFFF0000) | 0x01550000; /* dsr(txd), cts(rxd), rts(rs485_dir), rxd, txd */
+
+  udrv=ul_drv_new(UL_DRV_SYSLESS_PORT,     /* port */
+             UL_DRV_SYSLESS_IRQ,            /* irq */
+            UL_DRV_SYSLESS_BAUD,           /* baud */
+            UL_DRV_SYSLESS_MY_ADR_DEFAULT, /* my adr */
+       #ifdef CONFIG_OC_UL_DRV_U450_VARPINS
+         #ifdef CONFIG_OC_UL_DRV_U450_VARPINS_MSRSWAP
+            "16450-msrswap",               /* chip name */
+         #elif defined(CONFIG_OC_UL_DRV_U450_VARPINS_DIRNEG)
+            "16450-dirneg",                /* chip name */
+          #else
+            "16450",                       /* chip name */
+          #endif
+       #else /*CONFIG_OC_UL_DRV_U450_VARPINS*/
+            "16450",                       /* chip name */
+       #endif /*CONFIG_OC_UL_DRV_U450_VARPINS*/
+            0);                            /* baud base - default */
+
+  if (udrv==NULL)
+    return -1;
+
+  ul_drv_add_iac(udrv,UL_CMD_RDM,UL_IAC_OP_SND,ul_iac_call_rdm,NULL,0,0,NULL);
+  ul_drv_add_iac(udrv,UL_CMD_ERM,UL_IAC_OP_CALLBACK,ul_iac_call_erm,NULL,0,0,NULL);
+  ul_drv_add_iac(udrv,UL_CMD_WRM,UL_IAC_OP_REC,ul_iac_call_wrm,(char*)lpciap_buff,0,0,NULL);
+  ul_drv_add_iac(udrv,UL_CMD_DEB,UL_IAC_OP_CALLBACK,ul_iac_call_deb,NULL,0,0,NULL); 
+  ul_drv_add_iac(udrv,UL_CMD_RES,UL_IAC_OP_CALLBACK,ul_iac_call_res,NULL,0,0,NULL); 
+
+  return ul_drv_add_dev(udrv);
+}
+#endif /* CONFIG_OC_UL_DRV_SYSLESS */
+
+#ifdef CONFIG_OC_I2C_DRV_SYSLESS
+
+i2c_drv_t i2c_drv;
+
+int
+i2cInit(void)
+{
+
+  /* set io pins */
+  PINSEL0 = (PINSEL0 & ~0x000000F0) | 0x00000050; /* I2C - SCL, SDA */
+
+  if (i2c_drv_init(&i2c_drv, 
+               I2C_DRV_SYSLESS_PORT,
+               I2C_DRV_SYSLESS_IRQ,
+              I2C_DRV_SYSLESS_BITRATE,
+               I2C_DRV_SYSLESS_SLADR)<0) return -1;
+
+  return 1;
+}
+
+#endif /*CONFIG_OC_I2C_DRV_SYSLESS*/
+
+void _setup_board()
+{
+  // initialize the system
+  sysInit();                               
+
+  #ifdef WATCHDOG_ENABLED
+    lpc_watchdog_init(1,WATCHDOG_TIMEOUT_MS);
+    lpc_watchdog_feed();
+  #endif /* WATCHDOG_ENABLED */
+
+  // initialize the system timer
+  timerInit();
+
+  #ifdef CONFIG_STDIO_COM_PORT
+    uart0Init( B57600 , UART_8N1, UART_FIFO_8); 
+    init_system_stub();
+  #endif /* CONFIG_STDIO_COM_PORT */
+
+  #ifdef CONFIG_OC_UL_DRV_SYSLESS
+//    uld_debug_flg=0x3ff;
+    uLanInit();
+  #endif /* CONFIG_OC_UL_DRV_SYSLESS */
+  
+  #ifdef CONFIG_OC_I2C_DRV_SYSLESS
+    i2cInit();
+  #endif /* CONFIG_OC_I2C_DRV_SYSLESS */
+}
diff --git a/embedded/board/arm/ul_usb1/libs/bspbase/bspbase.h b/embedded/board/arm/ul_usb1/libs/bspbase/bspbase.h
new file mode 100644 (file)
index 0000000..5369f81
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _BSPBASE_H
+#define _BSPBASE_H
+
+#include <types.h>
+#include <lt_timer_types.h>
+
+extern volatile lt_ticks_t sys_timer_ticks;
+
+#define get_sys_timer_ticks() sys_timer_ticks
+
+#endif /* _BSPBASE_H */
diff --git a/embedded/board/arm/ul_usb1/libs/bspbase/kbd_io_hisc.c b/embedded/board/arm/ul_usb1/libs/bspbase/kbd_io_hisc.c
new file mode 100644 (file)
index 0000000..ff4d1d5
--- /dev/null
@@ -0,0 +1,88 @@
+#include <cpu_def.h>
+#include "kbd.h"
+
+unsigned char kbd_onerow(unsigned char scan)
+{
+       kbdisr_lock_level_t level;
+       unsigned int scan_mask=KBD_SCAN_MASK;
+       unsigned int scan_val;
+       unsigned int ret;
+       int delay=10;
+
+       kbdisr_lock(level);
+
+       #ifdef KBD_USE_IO_SETCLR_OPS
+       scan_val=(scan<<KBD_SCAN_BIT0) & scan_mask;
+        SET_OUT_PIN(KBD_PORT,scan_mask);
+        CLR_OUT_PIN(KBD_PORT,scan_val);
+       #else   
+       scan_val=(~scan<<KBD_SCAN_BIT0) & scan_mask;
+       KBD_DR|=scan_val;
+       KBD_DR&=scan_val|~scan_mask;
+       #endif /* KBD_USE_IO_SETCLR_OPS */
+       kbdisr_unlock(level);
+
+       while(delay--)
+               ret=KBD_SSR;
+       ret=KBD_SSR;
+
+       kbdisr_lock(level);
+       #ifdef KBD_USE_IO_SETCLR_OPS
+        SET_OUT_PIN(KBD_PORT,scan_mask);
+       #else   
+       KBD_DR |= scan_mask;
+       #endif /* KBD_USE_IO_SETCLR_OPS */
+       kbdisr_unlock(level);
+       
+       return (~ret>>KBD_RET_BIT0)&((1<<KBD_RET_CNT)-1);
+}
+
+void kbd_setio(void)
+{
+       kbdisr_lock_level_t level;
+       unsigned int scan_mask=KBD_SCAN_MASK;
+       #ifndef KBD_USE_IO_SETCLR_OPS
+       unsigned int ret_mask=KBD_RET_MASK;
+       #endif /* KBD_USE_IO_SETCLR_OPS */
+
+       kbdisr_lock(level);
+       
+       #ifdef KBD_USE_IO_SETCLR_OPS
+        SET_OUT_PIN(KBD_PORT,scan_mask);
+       #else   
+       KBD_DR|=scan_mask;
+       KBD_DDIR|=scan_mask;
+       KBD_DDIR&=~ret_mask;
+       KBD_PUEN|=ret_mask;
+       #endif /* KBD_USE_IO_SETCLR_OPS */
+
+       kbdisr_unlock(level);
+}
+
+const scan2key_t kbd_scan2key_hisc_keypad[]={
+       [0x00]={0,0},
+       [0x01]={'3',0},
+       [0x02]={'6',0},
+       [0x03]={'9',0},
+       [0x04]={'\r',0},
+       [0x05]={'A',0},
+       [0x06]={'2',0},
+       [0x07]={'5',0},
+       [0x08]={'8',0},
+       [0x09]={'0',0},
+       [0x0a]={'B',0},
+       [0x0b]={'1',0},
+       [0x0c]={'4',0},
+       [0x0d]={'7',0},
+       [0x0e]={'*',0},
+       [0x0f]={'C',0},
+};
+
+const scan2mod_t kbd_scan2mod_hisc_keypad[]={
+       {0,0,0,0}
+};
+
+scan2key_t *kbd_scan2key_tab=(scan2key_t*)kbd_scan2key_hisc_keypad;
+scan2mod_t *kbd_scan2mod_tab=(scan2mod_t*)kbd_scan2mod_hisc_keypad;
+
+
diff --git a/embedded/board/arm/ul_usb1/libs/bspbase/uart.c b/embedded/board/arm/ul_usb1/libs/bspbase/uart.c
new file mode 100644 (file)
index 0000000..86982a7
--- /dev/null
@@ -0,0 +1,117 @@
+/******************************************************************************
+ *
+ * $RCSfile: uart.c,v $
+ * $Revision: 1.1 $
+ *
+ * This module provides interface routines to the LPC ARM UARTs.
+ * Copyright 2004, R O SoftWare
+ * No guarantees, warrantees, or promises, implied or otherwise.
+ * May be used for hobby or commercial purposes provided copyright
+ * notice remains intact.
+ *
+ * reduced to see what has to be done for minimum UART-support by mthomas
+ *****************************************************************************/
+
+// #warning "this is a reduced version of the R O Software code"
+
+#include "uart.h"
+
+/* on LPC210x: UART0 TX-Pin=P0.2, RX-Pin=P0.1 
+   PINSEL0 has to be set to "UART-Function" = Function "01" 
+   for Pin 0.0 and 0.1 */
+   
+#define PINSEL_BITPIN0  0
+#define PINSEL_BITPIN1  2
+#define PINSEL_BITPIN2  4
+#define PINSEL_FIRST_ALT_FUNC   1
+#define PINSEL_SECOND_ALT_FUNC  2
+
+// Values of Bits 0-3 in PINSEL to activate UART0
+#define UART0_PINSEL    ((PINSEL_FIRST_ALT_FUNC<<PINSEL_BITPIN0)|(PINSEL_FIRST_ALT_FUNC<<PINSEL_BITPIN1))
+// Mask of Bits 0-4
+#define UART0_PINMASK      (0x0000000F)    /* PINSEL0 Mask for UART0 */
+
+// U0_LCR devisor latch bit 
+#define UART0_LCR_DLAB  7
+
+/*    baudrate divisor - use UART_BAUD macro
+ *    mode - see typical modes (uart.h)
+ *    fmode - see typical fmodes (uart.h)
+ *    NOTE: uart0Init(UART_BAUD(9600), UART_8N1, UART_FIFO_8); 
+ */
+void uart0Init(uint16_t baud, uint8_t mode, uint8_t fmode)
+{
+  volatile int i;
+
+  // setup Pin Function Select Register (Pin Connect Block) 
+  // make sure old values of Bits 0-4 are masked out and
+  // set them according to UART0-Pin-Selection
+  PINSEL0 = (PINSEL0 & ~UART0_PINMASK) | UART0_PINSEL; 
+
+  U0IER = 0x00;             // disable all interrupts
+  U0IIR = 0x00;             // clear interrupt ID register
+  U0LSR = 0x00;             // clear line status register
+
+  // set the baudrate - DLAB must be set to access DLL/DLM
+  U0LCR = (1<<UART0_LCR_DLAB); // set divisor latches (DLAB)
+  U0DLL = (uint8_t)baud;         // set for baud low byte
+  U0DLM = (uint8_t)(baud >> 8);  // set for baud high byte
+  
+  // set the number of characters and other
+  // user specified operating parameters
+  // Databits, Parity, Stopbits - Settings in Line Control Register
+  U0LCR = (mode & ~(1<<UART0_LCR_DLAB)); // clear DLAB "on-the-fly"
+  // setup FIFO Control Register (fifo-enabled + xx trig) 
+  U0FCR = fmode;
+
+  for(i=0;i<65000;i++);
+}
+
+int uart0Putch(int ch)
+{
+  while (!(U0LSR & ULSR_THRE))          // wait for TX buffer to empty
+    continue;                           // also either WDOG() or swap()
+
+  U0THR = (uint8_t)ch;  // put char to Transmit Holding Register
+  return (uint8_t)ch;      // return char ("stdio-compatible"?)
+}
+
+const char *uart0Puts(const char *string)
+{
+       char ch;
+       
+       while ((ch = *string)) {
+               if (uart0Putch(ch)<0) break;
+               string++;
+       }
+       
+       return string;
+}
+
+int uart0TxEmpty(void)
+{
+  return (U0LSR & (ULSR_THRE | ULSR_TEMT)) == (ULSR_THRE | ULSR_TEMT);
+}
+
+void uart0TxFlush(void)
+{
+  U0FCR |= UFCR_TX_FIFO_RESET;          // clear the TX fifo
+}
+
+
+/* Returns: character on success, -1 if no character is available */
+int uart0Getch(void)
+{
+  if (U0LSR & ULSR_RDR)                 // check if character is available
+    return U0RBR;                       // return character
+
+  return -1;
+}
+
+/* Returns: character on success, waits */
+int uart0GetchW(void)
+{
+       while ( !(U0LSR & ULSR_RDR) ); // wait for character 
+       return U0RBR;                // return character
+}
+
diff --git a/embedded/board/arm/ul_usb1/libs/bspbase/uart.h b/embedded/board/arm/ul_usb1/libs/bspbase/uart.h
new file mode 100644 (file)
index 0000000..f13906c
--- /dev/null
@@ -0,0 +1,65 @@
+/******************************************************************************
+ * based on software from:
+ * Copyright 2004, R O SoftWare
+ * No guarantees, warrantees, or promises, implied or otherwise.
+ * May be used for hobby or commercial purposes provided copyright
+ * notice remains intact.
+ * 
+ * reduced to learn what has to be done to enable and use UART0
+ *****************************************************************************/
+#ifndef INC_UART_H
+#define INC_UART_H
+
+#include <system_def.h>
+
+///////////////////////////////////////////////////////////////////////////////
+// use the following macros to determine the 'baud' parameter values
+// for uart0Init() and uart1Init()
+// CAUTION - 'baud' SHOULD ALWAYS BE A CONSTANT or
+// a lot of code will be generated.
+// Baud-Rate is calculated based on pclk (VPB-clock)
+// the devisor must be 16 times the desired baudrate
+#define UART_BAUD(baud) (uint16_t)((PCLK / ((baud) * 16.0)) + 0.5)
+
+///////////////////////////////////////////////////////////////////////////////
+// Definitions for typical UART 'baud' settings
+#define B1200         UART_BAUD(1200)
+#define B9600         UART_BAUD(9600)
+#define B19200        UART_BAUD(19200)
+#define B38400        UART_BAUD(38400)
+#define B57600        UART_BAUD(57600)
+#define B115200       UART_BAUD(115200)
+
+///////////////////////////////////////////////////////////////////////////////
+// Definitions for typical UART 'mode' settings
+#define UART_8N1      (uint8_t)(ULCR_CHAR_8 + ULCR_PAR_NO   + ULCR_STOP_1)
+#define UART_7N1      (uint8_t)(ULCR_CHAR_7 + ULCR_PAR_NO   + ULCR_STOP_1)
+#define UART_8N2      (uint8_t)(ULCR_CHAR_8 + ULCR_PAR_NO   + ULCR_STOP_2)
+#define UART_7N2      (uint8_t)(ULCR_CHAR_7 + ULCR_PAR_NO   + ULCR_STOP_2)
+#define UART_8E1      (uint8_t)(ULCR_CHAR_8 + ULCR_PAR_EVEN + ULCR_STOP_1)
+#define UART_7E1      (uint8_t)(ULCR_CHAR_7 + ULCR_PAR_EVEN + ULCR_STOP_1)
+#define UART_8E2      (uint8_t)(ULCR_CHAR_8 + ULCR_PAR_EVEN + ULCR_STOP_2)
+#define UART_7E2      (uint8_t)(ULCR_CHAR_7 + ULCR_PAR_EVEN + ULCR_STOP_2)
+#define UART_8O1      (uint8_t)(ULCR_CHAR_8 + ULCR_PAR_ODD  + ULCR_STOP_1)
+#define UART_7O1      (uint8_t)(ULCR_CHAR_7 + ULCR_PAR_ODD  + ULCR_STOP_1)
+#define UART_8O2      (uint8_t)(ULCR_CHAR_8 + ULCR_PAR_ODD  + ULCR_STOP_2)
+#define UART_7O2      (uint8_t)(ULCR_CHAR_7 + ULCR_PAR_ODD  + ULCR_STOP_2)
+
+///////////////////////////////////////////////////////////////////////////////
+// Definitions for typical UART 'fmode' settings
+#define UART_FIFO_OFF (0x00)
+#define UART_FIFO_1   (uint8_t)(UFCR_FIFO_ENABLE + UFCR_FIFO_TRIG1)
+#define UART_FIFO_4   (uint8_t)(UFCR_FIFO_ENABLE + UFCR_FIFO_TRIG4)
+#define UART_FIFO_8   (uint8_t)(UFCR_FIFO_ENABLE + UFCR_FIFO_TRIG8)
+#define UART_FIFO_14  (uint8_t)(UFCR_FIFO_ENABLE + UFCR_FIFO_TRIG14)
+
+void uart0Init(uint16_t baud, uint8_t mode, uint8_t fmode);
+int uart0Putch(int ch);
+uint16_t uart0Space(void);
+const char *uart0Puts(const char *string);
+int uart0TxEmpty(void);
+void uart0TxFlush(void);
+int uart0Getch(void);
+int uart0GetchW(void);
+
+#endif
diff --git a/embedded/board/arm/ul_usb1/libs/ldscripts/Makefile b/embedded/board/arm/ul_usb1/libs/ldscripts/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/board/arm/ul_usb1/libs/ldscripts/Makefile.omk b/embedded/board/arm/ul_usb1/libs/ldscripts/Makefile.omk
new file mode 100644 (file)
index 0000000..01e6b77
--- /dev/null
@@ -0,0 +1,5 @@
+# -*- makefile -*-
+
+lib_LDSCRIPTS = $(notdir $(wildcard $(SOURCES_DIR)/*.ld*))
+
+include_HEADERS = mem_loc.h keyval_loc.h
diff --git a/embedded/board/arm/ul_usb1/libs/ldscripts/keyval_loc.h b/embedded/board/arm/ul_usb1/libs/ldscripts/keyval_loc.h
new file mode 100644 (file)
index 0000000..2ee23e5
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _KEYVAL_LOC_H
+#define _KEYVAL_LOC_H
+
+extern int _keyval_start;
+extern int _keyval_page_len;
+
+#define KEYVAL_START ((unsigned int)&_keyval_start)
+#define KEYVAL_PAGE_LEN ((unsigned int)&_keyval_page_len)
+
+#endif  /* _KVPB_LOC */
diff --git a/embedded/board/arm/ul_usb1/libs/ldscripts/lpc2103.ld-cfg b/embedded/board/arm/ul_usb1/libs/ldscripts/lpc2103.ld-cfg
new file mode 100644 (file)
index 0000000..a29dfc8
--- /dev/null
@@ -0,0 +1,12 @@
+
+/* Memory Definitions */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00008000
+  RAM (rw) : ORIGIN = 0x40000000, LENGTH = 0x00001FE0
+  STACK (rw) : ORIGIN = 0x40000000 + 0x00001FE0 - 4, LENGTH = 4
+
+  FLASHVEC (rx) : ORIGIN = 0x00000000, LENGTH = 0x00000020
+  RAMVEC (w)  : ORIGIN = 0x40000000, LENGTH = 0x00000020
+}
+
diff --git a/embedded/board/arm/ul_usb1/libs/ldscripts/lpc2103.ld-flash b/embedded/board/arm/ul_usb1/libs/ldscripts/lpc2103.ld-flash
new file mode 100644 (file)
index 0000000..e1a20c6
--- /dev/null
@@ -0,0 +1,94 @@
+/***********************************************************************/
+/*                                                                     */
+/*  ROM.ld:  Linker Script File                                        */
+/*                                                                     */
+/***********************************************************************/
+ENTRY(_startup)
+
+INCLUDE "lpc2103.ld-cfg"
+
+STARTUP(startup.o) 
+
+PROVIDE (_setup_board = 0);
+
+/* Section Definitions */
+SECTIONS
+{
+
+  /* first section is .text which is used for code */
+  .text :
+  {
+    . = ALIGN(4);
+    *(.ivt)
+    *(.text)                   /* remaining code */
+    *(.rodata)                 /* read-only data (constants) */
+    *(.rodata*)
+    *(.glue_7)
+    *(.glue_7t)
+    _etext = ALIGN( 4 ) ;
+  } > FLASH
+
+  /* .data section which is used for initialized data */
+/*  .data : AT (_etext)\r*/
+  .data :
+          AT ( ADDR( .text ) + SIZEOF( .text ) )
+  {
+    . = ALIGN(4);
+    _data = .;
+    *(.data)
+    _edata = ALIGN( 4 ) ;
+  } > RAM
+  /* .bss section which is used for uninitialized data */
+  .bss (NOLOAD) :
+  {
+    . = ALIGN(4);
+    __bss_start = . ;
+    __bss_start__ = . ;
+    *(.bss)
+    *(COMMON)
+    __bss_end__ = ALIGN( 4 ) ;
+    end = ALIGN( 4 ) ;
+    _end = ALIGN( 4 ) ;
+  } > RAM
+
+  .stack :
+  {
+    _stack = .;
+  } > STACK
+
+
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+}
diff --git a/embedded/board/arm/ul_usb1/libs/ldscripts/lpc2105.ld-app b/embedded/board/arm/ul_usb1/libs/ldscripts/lpc2105.ld-app
new file mode 100644 (file)
index 0000000..4998f11
--- /dev/null
@@ -0,0 +1,99 @@
+/***********************************************************************/
+/*                                                                     */
+/*  ROM.ld:  Linker Script File                                        */
+/*                                                                     */
+/***********************************************************************/
+ENTRY(_startup)
+
+INCLUDE "lpc2105.ld-cfg"
+
+STARTUP(startup.o) 
+
+PROVIDE (_setup_board = 0);
+
+/* Section Definitions */
+SECTIONS
+{
+
+  /* first section is .text which is used for code */
+  .text :
+  {
+    . = ALIGN(4);
+    *(.text)                   /* remaining code */
+    *(.rodata)                 /* read-only data (constants) */
+    *(.rodata*)
+    *(.glue_7)
+    *(.glue_7t)
+    _etext = ALIGN( 4 ) ;
+  } > FLASHAPP
+
+  .keyval :
+  {
+    PROVIDE (_keyval_start = .);
+    PROVIDE (_keyval_page_len = KEYVAL_PAGE_LEN );
+  }> KEYVAL
+
+  /* .data section which is used for initialized data */
+/*  .data : AT (_etext)\r*/
+  .data :
+          AT ( ADDR( .text ) + SIZEOF( .text ) )
+  {
+    . = ALIGN(4);
+    _data = .;
+    *(.ivt)
+    *(.data)
+    _edata = ALIGN( 4 ) ;
+  } > RAM
+  /* .bss section which is used for uninitialized data */
+  .bss (NOLOAD) :
+  {
+    . = ALIGN(4);
+    __bss_start = . ;
+    __bss_start__ = . ;
+    *(.bss)
+    *(COMMON)
+    __bss_end__ = ALIGN( 4 ) ;
+    end = ALIGN( 4 ) ;
+    _end = ALIGN( 4 ) ;
+  } > RAM
+
+  .stack :
+  {
+    _stack = .;
+  } > STACK
+
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+}
diff --git a/embedded/board/arm/ul_usb1/libs/ldscripts/lpc2105.ld-boot b/embedded/board/arm/ul_usb1/libs/ldscripts/lpc2105.ld-boot
new file mode 100644 (file)
index 0000000..5ddb822
--- /dev/null
@@ -0,0 +1,104 @@
+/***********************************************************************/
+/*                                                                     */
+/*  ROM.ld:  Linker Script File                                        */
+/*                                                                     */
+/***********************************************************************/
+ENTRY(_startup)
+
+INCLUDE "lpc2105.ld-cfg"
+
+STARTUP(startup.o) 
+
+PROVIDE (_setup_board = 0);
+
+/* Section Definitions */
+SECTIONS
+{
+
+  /* first section is .text which is used for code */
+  .text :
+  {
+    . = ALIGN(4);
+    *(.ivt)
+    *(.text)                   /* remaining code */
+    *(.rodata)                 /* read-only data (constants) */
+    *(.rodata*)
+    *(.glue_7)
+    *(.glue_7t)
+    _etext = ALIGN( 4 ) ;
+  } > FLASHBOOT
+
+  .app :
+  {
+    PROVIDE (_mem_app_start = . );
+  } > FLASHAPP
+
+  .keyval :
+  {
+    PROVIDE (_keyval_start = .);
+    PROVIDE (_keyval_page_len = KEYVAL_PAGE_LEN );
+  }> KEYVAL
+
+  /* .data section which is used for initialized data */
+/*  .data : AT (_etext)\r*/
+  .data :
+          AT ( ADDR( .text ) + SIZEOF( .text ) )
+  {
+    . = ALIGN(4);
+    _data = .;
+    *(.data)
+    _edata = ALIGN( 4 ) ;
+  } > RAM
+  /* .bss section which is used for uninitialized data */
+  .bss (NOLOAD) :
+  {
+    . = ALIGN(4);
+    __bss_start = . ;
+    __bss_start__ = . ;
+    *(.bss)
+    *(COMMON)
+    __bss_end__ = ALIGN( 4 ) ;
+    end = ALIGN( 4 ) ;
+    _end = ALIGN( 4 ) ;
+  } > RAM
+
+  .stack :
+  {
+    _stack = .;
+  } > STACK
+
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+}
diff --git a/embedded/board/arm/ul_usb1/libs/ldscripts/lpc2105.ld-cfg b/embedded/board/arm/ul_usb1/libs/ldscripts/lpc2105.ld-cfg
new file mode 100644 (file)
index 0000000..d5a9ba9
--- /dev/null
@@ -0,0 +1,18 @@
+
+KEYVAL_PAGE_LEN = 0x00002000;
+
+/* Memory Definitions */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00020000
+  RAM (rw) : ORIGIN = 0x40000000, LENGTH = 0x00003FE0
+  STACK (rw) : ORIGIN = 0x40000000 + 0x00003FE0 - 4, LENGTH = 4
+
+  FLASHVEC (rx) : ORIGIN = 0x00000000, LENGTH = 0x00000020
+  FLASHBOOT (rx) : ORIGIN = 0x0000000, LENGTH = 0x0000A000
+  FLASHAPP (rx) : ORIGIN = 0x0000A000, LENGTH = 0x0001A000
+  KEYVAL (rx) : ORIGIN = 0x00001A000, LENGTH = 0x00004000
+
+  RAMVEC (w)  : ORIGIN = 0x40000000, LENGTH = 0x00000020
+}
+
diff --git a/embedded/board/arm/ul_usb1/libs/ldscripts/lpc2148.ld-app b/embedded/board/arm/ul_usb1/libs/ldscripts/lpc2148.ld-app
new file mode 100644 (file)
index 0000000..767081f
--- /dev/null
@@ -0,0 +1,99 @@
+/***********************************************************************/
+/*                                                                     */
+/*  ROM.ld:  Linker Script File                                        */
+/*                                                                     */
+/***********************************************************************/
+ENTRY(_startup)
+
+INCLUDE "lpc2148.ld-cfg"
+
+STARTUP(startup.o) 
+
+PROVIDE (_setup_board = 0);
+
+/* Section Definitions */
+SECTIONS
+{
+
+  /* first section is .text which is used for code */
+  .text :
+  {
+    . = ALIGN(4);
+    *(.text)                   /* remaining code */
+    *(.rodata)                 /* read-only data (constants) */
+    *(.rodata*)
+    *(.glue_7)
+    *(.glue_7t)
+    _etext = ALIGN( 4 ) ;
+  } > FLASHAPP
+
+  .keyval :
+  {
+    PROVIDE (_keyval_start = .);
+    PROVIDE (_keyval_page_len = KEYVAL_PAGE_LEN );
+  }> KEYVAL
+
+  /* .data section which is used for initialized data */
+/*  .data : AT (_etext)\r*/
+  .data :
+          AT ( ADDR( .text ) + SIZEOF( .text ) )
+  {
+    . = ALIGN(4);
+    _data = .;
+    *(.ivt)
+    *(.data)
+    _edata = ALIGN( 4 ) ;
+  } > RAM
+  /* .bss section which is used for uninitialized data */
+  .bss (NOLOAD) :
+  {
+    . = ALIGN(4);
+    __bss_start = . ;
+    __bss_start__ = . ;
+    *(.bss)
+    *(COMMON)
+    __bss_end__ = ALIGN( 4 ) ;
+    end = ALIGN( 4 ) ;
+    _end = ALIGN( 4 ) ;
+  } > RAM
+
+  .stack :
+  {
+    _stack = .;
+  } > STACK
+
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+}
diff --git a/embedded/board/arm/ul_usb1/libs/ldscripts/lpc2148.ld-boot b/embedded/board/arm/ul_usb1/libs/ldscripts/lpc2148.ld-boot
new file mode 100644 (file)
index 0000000..de00d81
--- /dev/null
@@ -0,0 +1,104 @@
+/***********************************************************************/
+/*                                                                     */
+/*  ROM.ld:  Linker Script File                                        */
+/*                                                                     */
+/***********************************************************************/
+ENTRY(_startup)
+
+INCLUDE "lpc2148.ld-cfg"
+
+STARTUP(startup.o) 
+
+PROVIDE (_setup_board = 0);
+
+/* Section Definitions */
+SECTIONS
+{
+
+  /* first section is .text which is used for code */
+  .text :
+  {
+    . = ALIGN(4);
+    *(.ivt)
+    *(.text)                   /* remaining code */
+    *(.rodata)                 /* read-only data (constants) */
+    *(.rodata*)
+    *(.glue_7)
+    *(.glue_7t)
+    _etext = ALIGN( 4 ) ;
+  } > FLASHBOOT
+
+  .app :
+  {
+    PROVIDE (_mem_app_start = . );
+  } > FLASHAPP
+
+  .keyval :
+  {
+    PROVIDE (_keyval_start = .);
+    PROVIDE (_keyval_page_len = KEYVAL_PAGE_LEN );
+  }> KEYVAL
+
+  /* .data section which is used for initialized data */
+/*  .data : AT (_etext)\r*/
+  .data :
+          AT ( ADDR( .text ) + SIZEOF( .text ) )
+  {
+    . = ALIGN(4);
+    _data = .;
+    *(.data)
+    _edata = ALIGN( 4 ) ;
+  } > RAM
+  /* .bss section which is used for uninitialized data */
+  .bss (NOLOAD) :
+  {
+    . = ALIGN(4);
+    __bss_start = . ;
+    __bss_start__ = . ;
+    *(.bss)
+    *(COMMON)
+    __bss_end__ = ALIGN( 4 ) ;
+    end = ALIGN( 4 ) ;
+    _end = ALIGN( 4 ) ;
+  } > RAM
+
+  .stack :
+  {
+    _stack = .;
+  } > STACK
+
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+}
diff --git a/embedded/board/arm/ul_usb1/libs/ldscripts/lpc2148.ld-cfg b/embedded/board/arm/ul_usb1/libs/ldscripts/lpc2148.ld-cfg
new file mode 100644 (file)
index 0000000..7534208
--- /dev/null
@@ -0,0 +1,18 @@
+
+KEYVAL_PAGE_LEN = 0x00001000;
+
+/* Memory Definitions */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00080000
+  RAM (rw) : ORIGIN = 0x40000000, LENGTH = 0x00007FE0
+  STACK (rw) : ORIGIN = 0x40000000 + 0x00007FE0 - 4, LENGTH = 4
+
+  FLASHVEC (rx) : ORIGIN = 0x00000000, LENGTH = 0x00000020
+  FLASHBOOT (rx) : ORIGIN = 0x0000000, LENGTH = 0x00020000
+  FLASHAPP (rx) : ORIGIN = 0x00020000, LENGTH = 0x00058000
+  KEYVAL (rx) : ORIGIN = 0x000078000, LENGTH = 0x00002000
+
+  RAMVEC (w)  : ORIGIN = 0x40000000, LENGTH = 0x00000020
+}
+
diff --git a/embedded/board/arm/ul_usb1/libs/ldscripts/mem_loc.h b/embedded/board/arm/ul_usb1/libs/ldscripts/mem_loc.h
new file mode 100644 (file)
index 0000000..77b24d1
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _MEM_LOC_H
+#define _MEM_LOC_H
+
+extern int _mem_app_start;
+
+#define MEM_APP_START ((unsigned int)&_mem_app_start)
+
+#endif  /* _MEM_LOC */
diff --git a/embedded/libs4c/Makefile b/embedded/libs4c/Makefile
new file mode 100644 (file)
index 0000000..bdb6d45
--- /dev/null
@@ -0,0 +1,15 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
+# DO NOT DELETE
diff --git a/embedded/libs4c/Makefile.omk b/embedded/libs4c/Makefile.omk
new file mode 100644 (file)
index 0000000..f76e30f
--- /dev/null
@@ -0,0 +1,3 @@
+# -*- makefile -*-
+
+SUBDIRS = keyval usb kbd i2c
\ No newline at end of file
diff --git a/embedded/libs4c/i2c/Makefile b/embedded/libs4c/i2c/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/libs4c/i2c/Makefile.omk b/embedded/libs4c/i2c/Makefile.omk
new file mode 100644 (file)
index 0000000..f58b859
--- /dev/null
@@ -0,0 +1,19 @@
+# -*- makefile -*-
+
+default_CONFIG  = CONFIG_OC_I2C_DRV_SYSLESS=n
+default_CONFIG += CONFIG_OC_I2C_CHIP_C552=y
+
+LOCAL_CONFIG_H = i2c_drv_config.h
+
+INCLUDES += -I . 
+
+ifeq ($(CONFIG_OC_I2C_DRV_SYSLESS),y) 
+lib_LIBRARIES = i2c_drv
+include_HEADERS += i2c_drv.h
+i2c_drv_SOURCES += i2c_drv.c
+
+ifeq ($(CONFIG_OC_I2C_CHIP_C552),y) 
+i2c_drv_SOURCES += i2c_c552.c 
+endif #CONFIG_OC_I2C_CHIP_C552
+
+endif #CONFIG_OC_I2C_DRV_SYSLESS
diff --git a/embedded/libs4c/i2c/i2c_c552.c b/embedded/libs4c/i2c/i2c_c552.c
new file mode 100644 (file)
index 0000000..56837d0
--- /dev/null
@@ -0,0 +1,396 @@
+/*******************************************************************
+  Components for embedded applications builded for
+  laboratory and medical instruments firmware  
+  i2c_mx1.c - I2C communication automata for M9328 MX1 microcontroller
+  Copyright holders and project originators
+    (C) 2001-2008 by Pavel Pisa pisa@cmp.felk.cvut.cz
+    (C) 2002-2008 by PiKRON Ltd. http://www.pikron.com
+    (C) 2007-2008 by Petr Smolik
+
+ The COLAMI components can be used and copied under next licenses
+   - MPL - Mozilla Public License
+   - GPL - GNU Public License
+   - LGPL - Lesser GNU Public License
+   - and other licenses added by project originators
+ Code can be modified and re-distributed under any combination
+ of the above listed licenses. If contributor does not agree with
+ some of the licenses, he can delete appropriate line.
+ Warning, if you delete all lines, you are not allowed to
+ distribute code or build project.
+ *******************************************************************/
+
+
+#include <system_def.h>
+#include <hal_intr.h>
+#include "i2c_drv_config.h"
+#include "i2c_drv.h"
+
+int c552_poll(i2c_drv_t *drv);
+void c552_irq_handler(int intno, void *dev_id);
+static int c552_ctrl_fnc(struct i2c_drv *drv, int ctrl, void *p);
+
+// I2C Registers
+#define C552_CONSET(port)  (((i2cRegs_t *)(port))->conset)     /* Control Set Register */
+#define C552_STAT(port)    (((i2cRegs_t *)(port))->stat)       /* Status Register */
+#define C552_DAT(port)     (((i2cRegs_t *)(port))->dat)        /* Data Register */
+#define C552_ADR(port)     (((i2cRegs_t *)(port))->adr)        /* Slave Address Register */
+#define C552_SCLH(port)    (((i2cRegs_t *)(port))->sclh)       /* SCL Duty Cycle Register (high half word) */
+#define C552_SCLL(port)    (((i2cRegs_t *)(port))->scll)       /* SCL Duty Cycle Register (low half word) */
+#define C552_CONCLR(port)  (((i2cRegs_t *)(port))->conclr)     /* Control Clear Register */
+
+#define C552CON_AA     (1 << 2)
+#define C552CON_SI     (1 << 3)
+#define C552CON_STO    (1 << 4)
+#define C552CON_STA    (1 << 5)
+#define C552CON_EN     (1 << 6)
+
+#define C552CON_AAC    (1 << 2)
+#define C552CON_SIC    (1 << 3)
+#define C552CON_STAC   (1 << 5)
+#define C552CON_ENC    (1 << 6)
+
+/***************************************************************************/
+int c552_init_start(struct i2c_drv *drv, int port, int irq, int bitrate, int sladr)
+{
+  C552_ADR(port)=sladr;
+  C552_SCLH(port)=((PCLK/2)/bitrate); //minimal value
+  C552_SCLL(port)=((PCLK/2)/bitrate);
+  drv->irq=irq;
+  drv->port=port;
+  drv->sfnc_act=NULL;
+  drv->ctrl_fnc=c552_ctrl_fnc;
+  drv->poll_fnc=c552_poll;
+  drv->flags=I2C_DRV_ON;    /* todo - use atomic operation */
+  C552_CONCLR(port)=0x6C;   /* clearing all flags */
+  C552_CONSET(port)=C552CON_EN;
+  HAL_INTERRUPT_ATTACH(irq,c552_irq_handler,drv);  
+  HAL_INTERRUPT_UNMASK(irq);
+  return 0;
+}
+
+static int c552_sfnc_ms_end(struct i2c_drv *drv);
+static inline i2c_msg_head_t *c552_sfnc_sl_prep(struct i2c_drv *drv, int cmd, int rxtx);
+
+/***************************************************************************/
+static int c552_sfnc_ms_end(struct i2c_drv *drv)
+{
+  i2c_msg_head_t *msg=drv->msg_act;
+
+  if(msg) {
+    if((msg->flags&I2C_MSG_CB_END) && (msg->callback))
+      msg->callback(drv,I2C_MSG_CB_END,msg);
+    if(msg->flags&I2C_MSG_REPEAT){
+      drv->master_queue=msg->next;
+    }else{
+      i2c_drv_queue_msg(msg->flags&I2C_MSG_NOPROC?NULL:&drv->proc_queue,msg);
+    }
+    msg->flags|=I2C_MSG_FINISHED;
+  }
+
+  if(drv->master_queue) {
+    /* there is some more work for master*/
+    /* We need to request start of the next transfer somewhere */
+    C552_CONSET(drv->port)=C552CON_STA;
+  } else {
+    drv->flags&=~I2C_DRV_MS_INPR;
+  }
+
+  drv->msg_act = NULL;
+  return 0;
+}
+
+static inline
+i2c_msg_head_t *c552_sfnc_sl_prep(struct i2c_drv *drv, int cmd, int rxtx)
+{
+  i2c_msg_head_t *msg=drv->slave_queue;
+  if(!msg) do {
+    if((msg->flags&rxtx) && !((cmd^msg->sl_cmd)&msg->sl_msk)){
+      drv->slave_queue=msg;
+      if((msg->flags&I2C_MSG_CB_START) && (msg->callback))
+        msg->callback(drv,I2C_MSG_CB_START|rxtx,msg);
+      return msg;
+    }
+  } while((msg=msg->next)!=drv->slave_queue);
+  return NULL;
+}
+
+/***************************************************************************/
+static int c552_ctrl_fnc(struct i2c_drv *drv, int ctrl, void *p)
+{
+  unsigned long saveif;
+  switch(ctrl){
+    case I2C_CTRL_MS_RQ:
+      if(!(drv->flags&I2C_DRV_ON))
+        return -1;
+      if(!drv->master_queue)
+        return 0;
+      save_and_cli(saveif);
+      if(!(drv->flags&I2C_DRV_MS_INPR)) {
+        drv->flags|=I2C_DRV_MS_INPR;
+       drv->flags&=~I2C_DRV_NA;
+        C552_CONSET(drv->port)=C552CON_STA;
+      }
+      restore_flags(saveif);
+      return 0;
+    default:
+      return -1;
+  }
+  return 0;
+}
+
+/***************************************************************************/
+int c552_poll(i2c_drv_t *drv)
+{
+  i2c_msg_head_t *msg;
+
+  if((msg=drv->proc_queue)!=NULL){
+    i2c_drv_queue_msg(NULL,msg);
+    if((msg->flags&I2C_MSG_CB_PROC) && (msg->callback))
+      msg->callback(drv,I2C_MSG_CB_PROC,msg);
+  }  
+  return 0;
+}
+
+int i2c_irq_seq_num=0;
+
+/***************************************************************************/
+void c552_irq_handler(int intno, void *dev_id)
+{
+  i2c_drv_t *drv;
+  i2c_msg_head_t *msg;
+  int port;
+  int stat;
+
+  drv=(i2c_drv_t*)dev_id;
+  if(drv->magic!=I2C_DRV_MAGIC)
+  {
+    #ifdef FOR_LINUX_KERNEL
+     panic("i2c_irq_handler : BAD drv magic !!!");
+    #elif defined(_WIN32)
+     I2C_PRINTF("i2c_irq_handler : BAD drv magic !!!\n");
+     return FALSE;
+    #elif defined(__DJGPP__)||defined(CONFIG_OC_I2C_DRV_SYSLESS)
+     I2C_PRINTF("i2c_irq_handler : BAD drv magic !!!\n");
+     return;
+    #else
+     error("i2c_irq_handler : BAD drv magic !!!");
+    #endif
+  }
+  drv->flags&=~I2C_DRV_NA;
+
+  port=drv->port;  
+  msg=drv->msg_act;
+
+  stat=C552_STAT(port);
+
+  switch(stat) {
+    case 0x00: 
+      /* Bus Error has occured */ 
+      drv->msg_act=NULL;
+      C552_CONSET(port)=C552CON_STO;
+      if(drv->master_queue) {
+        /* there is some work for master*/
+        C552_CONSET(port)=C552CON_STA;
+      }
+      break;
+    case 0x08: /* MS_STA */
+      /* the initial start condition has been sent */
+      if(!drv->master_queue) {
+        C552_CONCLR(port)=C552CON_STAC;
+        C552_CONSET(port)=C552CON_STO;
+       drv->msg_act=NULL;
+       break;
+      }
+      C552_CONCLR(port)=C552CON_STAC;
+      C552_CONSET(port)=C552CON_AA;
+
+      msg=drv->master_queue;
+      drv->msg_act=msg;
+      msg->tx_len=msg->rx_len=0;
+
+      if((msg->flags&I2C_MSG_CB_START) && (msg->callback))
+        msg->callback(drv,I2C_MSG_CB_START,msg);
+
+      if (msg->flags&I2C_MSG_MS_TX) {
+        /* proceed Tx request first */
+        C552_DAT(port) = msg->addr&~1;
+       break;
+      }
+      /* if there is no request for transmit, continue by Rx immediately */
+    case 0x10: /* MS_REPS */
+      /* the repeated start has been successfully sent, continue by Rx */
+      C552_CONCLR(port)=C552CON_STAC;
+      C552_CONSET(port)=C552CON_AA;
+      C552_DAT(port) = msg->addr|1;
+      if (!msg || !(msg->flags&I2C_MSG_MS_RX)) {
+        /* there are no data to be received */
+        C552_CONSET(port)=C552CON_STO;
+        c552_sfnc_ms_end(drv);
+      } else {
+        msg->rx_len=0;
+      }
+      break;
+    case 0x18:
+      /* sent SLA W received ACK */
+    case 0x28:
+      /* sent DATA received ACK */
+      if (msg->tx_len<msg->tx_rq) {
+        C552_DAT(port) = msg->tx_buf[msg->tx_len];
+        msg->tx_len++;
+        break;
+      }
+      /* all data has been sent */
+      if (!(msg->flags&I2C_MSG_MS_RX)) {
+        C552_CONSET(port)=C552CON_STO;
+        c552_sfnc_ms_end(drv);
+      } else {
+        C552_CONSET(port)=C552CON_STA;
+      }
+      break;
+    case 0x30:
+      /* sent DATA received NACK */
+    case 0x48:
+      /* sent SLA R received ACK */
+    case 0x20:
+      /* vyslano SLA W prijato NACK */
+      C552_CONSET(port)=C552CON_STO;
+      msg->flags|=I2C_MSG_FAIL;
+      c552_sfnc_ms_end(drv);
+      break;
+    case 0x38:
+      /* arbitration lost during Tx */
+      C552_CONSET(port)=C552CON_STA;
+      break;
+    case 0x40:
+      /* sent SLA R received ACK */
+      if (msg->rx_rq==1)
+        C552_CONCLR(port)=C552CON_AAC;
+      break;
+    case 0x50:
+      /* received DATA sent ACK */   
+      msg->rx_buf[msg->rx_len]= C552_DAT(port);
+      msg->rx_len++;
+      if (msg->rx_rq==msg->rx_len)
+        C552_CONCLR(port)=C552CON_AAC;
+      break;
+    case 0x58:
+      /* received DATA sent NACK */   
+      msg->rx_buf[msg->rx_len]= C552_DAT(port);
+      msg->rx_len++;
+      C552_CONSET(port)=C552CON_STO;
+      c552_sfnc_ms_end(drv);
+      break;
+
+    /*** slave mode ***/
+
+    case 0x68:
+      /* received own SLA W sent ACK after arbitration lost */
+
+    case 0x78:
+      /* received Generall CALL sent ACK after arbitration lost */
+      C552_CONSET(port)=C552CON_STA;
+
+    case 0x60:
+      /* received own SLA W sent ACK */
+
+    case 0x70:
+      /* received Generall CALL sent ACK */
+      if(!drv->slave_queue) {
+        C552_CONCLR(port)=C552CON_AAC;
+       break;
+      }
+      C552_CONSET(port)=C552CON_AA;
+      drv->flags|=I2C_DRV_SL_CEXP|I2C_DRV_SL_INRX;
+      break;
+
+    case 0x80:
+      /* SLA W : received DATA sent ACK */
+
+    case 0x90:
+      /* GCall : received DATA sent ACK */
+
+      if(drv->flags&I2C_DRV_SL_CEXP){
+        drv->flags&=~I2C_DRV_SL_CEXP;
+       drv->sl_last_cmd=C552_DAT(port);
+       msg=c552_sfnc_sl_prep(drv, drv->sl_last_cmd, I2C_MSG_SL_RX);
+        drv->msg_act=msg;
+      }
+      if(!msg || (msg->rx_len>=msg->rx_rq)){
+        C552_CONCLR(port)=C552CON_AAC;
+       break;
+      }
+      msg->rx_buf[msg->rx_len]= C552_DAT(port);
+      msg->rx_len++;
+      break;
+
+    case 0x88:
+      /* SLA W : received DATA sent NACK */
+      /* may it be, the handling should fall into A0 state */
+
+    case 0x98:
+      /* GCall : received DATA sent NACK */
+      /* may it be, the handling should fall into A0 state */
+
+      C552_CONSET(port)=C552CON_AA;
+      break;
+
+    case 0xA0:
+      /* Slave : Repeated START or STOP */
+      if(msg && (msg->flags&I2C_MSG_CB_END) && (msg->callback)) {
+        int cbcode;
+       if(drv->flags&I2C_DRV_SL_INRX)
+          cbcode=I2C_MSG_CB_END|I2C_MSG_SL_RX;
+       else
+          cbcode=I2C_MSG_CB_END|I2C_MSG_SL_TX;
+        msg->callback(drv,cbcode,msg);
+      }
+      C552_CONSET(port)=C552CON_AA;
+      break;
+
+    case 0xB0:
+      /* received own SLA R sent ACK  after arbitration lost */
+      C552_CONSET(port)=C552CON_STA;
+
+    case 0xA8:
+      /* received own SLA R sent ACK */
+      drv->flags&=~I2C_DRV_SL_INRX;
+      msg=c552_sfnc_sl_prep(drv, drv->sl_last_cmd, I2C_MSG_SL_RX);
+      drv->msg_act=msg;
+      if(!msg) {
+        C552_CONCLR(port)=C552CON_AAC;
+       break;
+      }
+      C552_CONSET(port)=C552CON_AA;
+
+    case 0xB8:
+      /* SLA R : sent DATA received ACK */
+      if(!msg || (msg->tx_len>=msg->tx_rq)){
+        C552_DAT(port) = 0xff;
+       break;
+      }
+      C552_DAT(port) = msg->tx_buf[msg->tx_len];
+      msg->tx_len++;
+      break;
+
+    case 0xC0:
+      /* SLA R : sent DATA received NACK */
+      /* the A0 state is not enerred most probably */
+
+    case 0xC8:
+      /* SLA R : last data sent, DATA (AA=0) received ACK */
+      /* the A0 state is not enerred most probably */
+      C552_CONSET(port)=C552CON_AA;
+
+      if(msg && (msg->flags&I2C_MSG_CB_END) && (msg->callback)) {
+        msg->callback(drv,I2C_MSG_CB_END|I2C_MSG_SL_TX,msg);
+      }
+      break;
+
+    default: break;
+  }
+
+  /* vymaz SI bit */
+  C552_CONCLR(port)=C552CON_SIC;
+}
diff --git a/embedded/libs4c/i2c/i2c_drv.c b/embedded/libs4c/i2c/i2c_drv.c
new file mode 100644 (file)
index 0000000..3a2f12a
--- /dev/null
@@ -0,0 +1,182 @@
+/*******************************************************************
+  Components for embedded applications builded for
+  laboratory and medical instruments firmware  
+  i2c_mx1.c - I2C communication automata for M9328 MX1 microcontroller
+  Copyright holders and project originators
+    (C) 2001-2004 by Pavel Pisa pisa@cmp.felk.cvut.cz
+    (C) 2002-2004 by PiKRON Ltd. http://www.pikron.com
+    (C) 2007-2008 by Petr Smolik
+
+ The COLAMI components can be used and copied under next licenses
+   - MPL - Mozilla Public License
+   - GPL - GNU Public License
+   - LGPL - Lesser GNU Public License
+   - and other licenses added by project originators
+ Code can be modified and re-distributed under any combination
+ of the above listed licenses. If contributor does not agree with
+ some of the licenses, he can delete appropriate line.
+ Warning, if you delete all lines, you are not allowed to
+ distribute code or build project.
+ *******************************************************************/
+
+
+#include <system_def.h>
+#include <string.h>
+#include "i2c_drv_config.h"
+#include "i2c_drv.h"
+
+/***************************************************************************/
+int  
+i2c_drv_init(i2c_drv_t *drv, int port, int irq, int bitrate,int sladr) 
+{
+  int r=-1;
+  memset(drv,0,sizeof(i2c_drv_t));
+  drv->magic=I2C_DRV_MAGIC;
+ #ifdef CONFIG_OC_I2C_CHIP_C552
+  r=c552_init_start(drv,port,irq,bitrate,sladr);
+ #endif /* CONFIG_OC_I2C_CHIP_C552 */
+  if (r<0) return r;
+  return 0;
+}
+
+/********************************************************************/
+/* Generic I2C functions */
+
+void i2c_drv_queue_msg(i2c_msg_head_t **queue, i2c_msg_head_t *msg)
+{
+  I2C_IRQ_LOCK_FINI
+  i2c_msg_head_t *prev, *next;
+  I2C_IRQ_LOCK;
+  if(msg->on_queue){
+    if(msg->next==msg){
+      if(*msg->on_queue==msg)
+        *msg->on_queue=NULL;
+    }else{
+      msg->next->prev=msg->prev;
+      msg->prev->next=msg->next;
+      if(*msg->on_queue==msg)
+        *msg->on_queue=msg->next;
+    }
+  }
+  if((msg->on_queue=queue)!=NULL){
+    if((next=*queue)!=NULL){
+      msg->prev=prev=next->prev;
+      msg->next=next;
+      next->prev=msg;
+      prev->next=msg;
+    }else{
+      *queue=msg->prev=msg->next=msg;
+    }
+  }
+  I2C_IRQ_UNLOCK;
+  return;
+}
+
+int i2c_drv_master_msg_ins(i2c_drv_t *drv, i2c_msg_head_t *msg)
+{
+  if(!drv) return -1;
+  if(!(drv->flags&I2C_DRV_ON)) return -1;
+  if(!msg->tx_buf) msg->flags&=~I2C_MSG_MS_TX;
+  if(!msg->rx_buf) msg->flags&=~I2C_MSG_MS_RX;
+  i2c_drv_queue_msg(&drv->master_queue,msg);
+  drv->ctrl_fnc(drv,I2C_CTRL_MS_RQ,NULL);
+  return 0;
+}
+
+int i2c_drv_master_msg_rem(i2c_drv_t *drv, i2c_msg_head_t *msg)
+{
+  int act;
+  I2C_IRQ_LOCK_FINI
+  do {
+    i2c_drv_queue_msg(NULL,msg);
+    I2C_IRQ_LOCK;
+    act = (msg==drv->msg_act);
+    if(act) {
+      drv->msg_act=NULL;
+    }
+    I2C_IRQ_UNLOCK;    
+  } while(msg->on_queue || act);
+  return 0;
+}
+
+int i2c_drv_flush_all(i2c_drv_t *drv)
+{
+  I2C_IRQ_LOCK_FINI
+  i2c_msg_head_t *msg, *next;
+  i2c_msg_head_t *queue[3];
+  int quenum;
+
+  I2C_IRQ_LOCK;
+    queue[0]=drv->master_queue;
+    queue[1]=drv->slave_queue;
+    queue[2]=drv->proc_queue;
+    drv->master_queue=NULL;
+    drv->slave_queue=NULL;
+    drv->proc_queue=NULL;
+    drv->msg_act=NULL;
+  I2C_IRQ_UNLOCK;    
+  for(quenum=0;quenum<3;quenum++){
+    msg=queue[quenum];
+    if(!msg) continue;
+    msg->prev->next=NULL;
+    for(;msg;msg=next){
+      next=msg->next;
+      msg->flags|=I2C_MSG_FAIL;
+      msg->on_queue=NULL;
+      if((msg->flags&I2C_MSG_CB_PROC) && (msg->callback))
+       msg->callback(drv,I2C_MSG_CB_PROC,msg);
+    }
+  }
+  return 0;
+}
+
+int i2c_drv_master_transfer_callback(struct i2c_drv *drv, int code, struct i2c_msg_head *msg)
+{
+  if(code!=I2C_MSG_CB_PROC) return 0;
+  set_bit(0,&(msg->private));
+  return 0;
+}
+
+
+int i2c_drv_master_transfer(i2c_drv_t *drv, int addr, int tx_rq, int rx_rq,
+                   void *tx_buf, void *rx_buf, int *ptx_len, int *prx_len)
+{
+  i2c_msg_head_t msg;
+  
+  msg.flags = I2C_MSG_CB_PROC;
+  msg.addr = addr;
+  msg.tx_rq = tx_rq;
+  msg.rx_rq = rx_rq;
+  msg.tx_buf = tx_buf;
+  msg.rx_buf = rx_buf;
+  msg.on_queue = NULL;
+  msg.callback = i2c_drv_master_transfer_callback;
+  msg.private = 0;
+
+  if(msg.tx_buf)
+    msg.flags |= I2C_MSG_MS_TX;
+
+  if(msg.rx_buf && (msg.rx_rq>=1))
+    msg.flags |= I2C_MSG_MS_RX;
+
+  if(!(msg.flags & (I2C_MSG_MS_TX | I2C_MSG_MS_RX)))
+    return 0;
+
+  if(i2c_drv_master_msg_ins(drv, &msg)<0) 
+    return -1;
+
+  /* wait for message process */
+  while(test_bit(0,&(msg.private))==0)
+    drv->poll_fnc(drv);
+
+  if(ptx_len) *ptx_len = msg.tx_len;
+  if(prx_len) *prx_len = msg.rx_len;
+  
+  if(msg.flags & I2C_MSG_FAIL)
+    return -1;
+  
+  return msg.tx_len+msg.rx_len;
+}
+
diff --git a/embedded/libs4c/i2c/i2c_drv.h b/embedded/libs4c/i2c/i2c_drv.h
new file mode 100644 (file)
index 0000000..50725d1
--- /dev/null
@@ -0,0 +1,122 @@
+/*******************************************************************
+  Components for embedded applications builded for
+  laboratory and medical instruments firmware  
+  i2c_drv.h - I2C communication automat interface 
+  Copyright holders and project originators
+    (C) 2001-2008 by Pavel Pisa pisa@cmp.felk.cvut.cz
+    (C) 2002-2008 by PiKRON Ltd. http://www.pikron.com
+    (C) 2007-2008 by Petr Smolik
+
+ The COLAMI components can be used and copied under next licenses
+   - MPL - Mozilla Public License
+   - GPL - GNU Public License
+   - LGPL - Lesser GNU Public License
+   - and other licenses added by project originators
+ Code can be modified and re-distributed under any combination
+ of the above listed licenses. If contributor does not agree with
+ some of the licenses, he can delete appropriate line.
+ Warning, if you delete all lines, you are not allowed to
+ distribute code or build project.
+ *******************************************************************/
+
+#ifndef _I2C_DRV_H_
+#define _I2C_DRV_H_
+
+#include <types.h>
+#include <cpu_def.h>
+
+#if defined(CONFIG_OC_I2C_DRV_SYSLESS)
+  #define I2C_IRQ_LOCK_FINI unsigned long i2c_irq_lock_flags=0;
+  #define I2C_IRQ_LOCK \
+    {save_flags(i2c_irq_lock_flags);cli();}
+  #define I2C_IRQ_UNLOCK \
+    {restore_flags(i2c_irq_lock_flags);}
+  #define I2C_MB()       {asm volatile ("":::"memory");}
+#endif
+
+struct i2c_drv;
+
+#define I2C_MSG_TX       0x001
+#define I2C_MSG_RX       0x002
+#define I2C_MSG_MS_TX    I2C_MSG_TX
+#define I2C_MSG_MS_RX    I2C_MSG_RX
+#define I2C_MSG_SL_TX    I2C_MSG_TX
+#define I2C_MSG_SL_RX    I2C_MSG_RX
+#define I2C_MSG_SLAVE    0x004
+#define I2C_MSG_FAIL     0x008
+#define I2C_MSG_REPEAT   0x010
+#define I2C_MSG_NOPROC   0x020
+#define I2C_MSG_FINISHED 0x040
+#define I2C_MSG_CB_START 0x100
+#define I2C_MSG_CB_END   0x200
+#define I2C_MSG_CB_PROC  0x400
+
+typedef struct i2c_msg_head {
+    unsigned long flags;/* message flags */
+    uint8_t  sl_cmd;   /* command for slave queue lookup */
+    uint8_t  sl_msk;   /* sl_cmd match mask */
+    uint16_t addr;     /* message destination address */
+    uint16_t tx_rq;    /* requested TX transfer length */
+    uint16_t rx_rq;    /* requested RX transfer length */
+    uint16_t tx_len;   /* finished TX transfer length */
+    uint16_t rx_len;   /* finished RX transfer length */
+    uint8_t *tx_buf;   /* pointer to TX data */
+    uint8_t *rx_buf;   /* pointer to RX data */
+    struct i2c_msg_head *prev;
+    struct i2c_msg_head *next;
+    struct i2c_msg_head **on_queue;
+    int (*callback)(struct i2c_drv *ifc, int code, struct i2c_msg_head *msg);
+    unsigned long private;
+  } i2c_msg_head_t;
+
+typedef int (i2c_sfnc_t)(struct i2c_drv *drv, int code);
+typedef int (i2c_ctrl_fnc_t)(struct i2c_drv *drv, int ctrl, void *p);
+
+#define I2C_DRV_ON      1 /* flag indicating that driver is ready to operate */
+#define I2C_DRV_MS_INPR 2 /* master request in in progress */
+#define I2C_DRV_NA      4 /* driver is not active for some period */
+#define I2C_DRV_SL_CEXP 8 /* slave expect receive of the first byte */
+#define I2C_DRV_SL_INRX 0x10 /* slave in mode */
+
+#define I2C_DRV_MAGIC 0x12345432
+
+typedef struct i2c_drv {
+    int        magic;          /* magic number */
+    int        irq;            /* irq number */
+    long port;         /* base port number */
+    uint8_t flags;
+    uint16_t self_addr;
+    i2c_msg_head_t *master_queue;
+    i2c_msg_head_t *slave_queue;
+    i2c_msg_head_t *proc_queue;
+    i2c_msg_head_t *msg_act;
+    i2c_sfnc_t *sfnc_act;
+    void *failed;
+    i2c_ctrl_fnc_t *ctrl_fnc;
+    int (*poll_fnc)(struct i2c_drv *drv);
+    uint8_t sl_last_cmd; /* last received slave command */
+  } i2c_drv_t;
+
+#define I2C_CTRL_MS_RQ 1
+
+#ifdef CONFIG_OC_I2C_CHIP_C552
+int c552_init_start(struct i2c_drv *drv, int port, int irq, int bitrate, int sladr);
+#endif /* CONFIG_OC_I2C_CHIP_C552 */
+
+void i2c_drv_queue_msg(i2c_msg_head_t **queue, i2c_msg_head_t *msg);
+int  i2c_drv_init(i2c_drv_t *drv, int port, int irq, int bitrate,int sladr);
+int  i2c_drv_master_msg_ins(i2c_drv_t *drv, i2c_msg_head_t *msg);
+int  i2c_drv_master_msg_rem(i2c_drv_t *drv, i2c_msg_head_t *msg);
+int  i2c_drv_flush_all(i2c_drv_t *drv);
+int  i2c_drv_master_transfer(i2c_drv_t *drv, int addr, int tx_rq, int rx_rq,
+                   void *tx_buf, void *rx_buf, int *ptx_len, int *prx_len);
+
+#ifdef I2C_LOG_ENABLE
+  /* todo */
+#else
+  #define I2C_PRINTF(x,args...) 
+#endif
+
+#endif /* _I2C_DRV_H_ */
diff --git a/embedded/libs4c/kbd/Makefile b/embedded/libs4c/kbd/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/libs4c/kbd/Makefile.omk b/embedded/libs4c/kbd/Makefile.omk
new file mode 100644 (file)
index 0000000..72023f5
--- /dev/null
@@ -0,0 +1,9 @@
+# -*- makefile -*-
+
+default_CONFIG = CONFIG_KBD=n
+
+ifeq ($(CONFIG_KBD),y) 
+lib_LIBRARIES = kbd
+include_HEADERS += kbd.h
+kbd_SOURCES += kbd_base.c kbd_dev_ops.c
+endif #CONFIG_KBD
diff --git a/embedded/libs4c/kbd/kbd.h b/embedded/libs4c/kbd/kbd.h
new file mode 100644 (file)
index 0000000..6721c8d
--- /dev/null
@@ -0,0 +1,45 @@
+#include <system_def.h>
+
+#ifndef KEY_DEFAULT_TIMES
+  #define KEY_PUSH_T   20
+  #define KEY_RELEASE_T        10
+  #define KEY_REPFIRST_T 800
+  #define KEY_REPNEXT_T        300
+#endif /* KEY_DEFAULT_TIMES */
+
+typedef struct {
+       kbd_key_t bc;
+       kbd_key_t sc;
+} scan2key_t;
+
+typedef struct {
+       int scan;
+       int flag;
+       kbd_keymod_t is_mod;
+       kbd_keymod_t set_mod;
+       kbd_keymod_t xor_mod;
+} scan2mod_t;
+
+#define KBDMOD_SGM_SC          0x8000
+#define KBDMOD_SGM_RELEASE     0x0080
+
+extern int key_last_changed;
+extern kbd_keymod_t key_mod;
+extern unsigned char key_hit;
+extern short key_use_timer;
+extern unsigned char key_down_arr[KBD_SCAN_CNT];
+
+unsigned char kbd_onerow(unsigned char scan);
+void kbd_setio(void);
+
+int kbd_scan();
+void kbd_scan2mod(int scan_code);
+int kbd_down();
+kbd_key_t kbd_scan2key(int scan);
+
+int kbd_Open(KBDDEVICE *pkd);
+void kbd_Close(void);
+void kbd_GetModifierInfo(kbd_keymod_t *modifiers, kbd_keymod_t *curmodifiers);
+int kbd_Read(kbd_key_t *buf, kbd_keymod_t *modifiers, kbd_scan_code_t *scancode);
+int kbd_Poll(void);
+
diff --git a/embedded/libs4c/kbd/kbd_base.c b/embedded/libs4c/kbd/kbd_base.c
new file mode 100644 (file)
index 0000000..f59dd52
--- /dev/null
@@ -0,0 +1,183 @@
+#include "kbd.h"
+
+extern scan2key_t *kbd_scan2key_tab;
+extern scan2mod_t *kbd_scan2mod_tab;
+
+/* State of keyboard matrix and key press reporting */
+
+unsigned char key_down_arr[KBD_SCAN_CNT];
+unsigned char key_chng_arr[KBD_SCAN_CNT];
+unsigned char key_hit;
+
+kbd_keymod_t key_mod;
+
+int key_last_changed;
+
+/* Internal state for repeat processing */
+
+short key_use_timer;
+short key_state;
+kbd_interval_t key_time;
+
+#define KEY_STATE_IDLE     0
+#define KEY_STATE_PUSH     1
+#define KEY_STATE_RELEASE  2
+#define KEY_STATE_REPEAT   4
+#define KEY_STATE_NOISE    8
+#define KEY_STATE_BUSY     (KEY_STATE_PUSH|KEY_STATE_RELEASE)
+
+
+/**
+ * kbd_scan - Scan keyboard matrix and report requests for state change
+ *
+ * Scans keyboard matrix connected row by row by calling function
+ * mx1_kbd_onerow(). Number of scanned output lines is defined
+ * by %KBD_SCAN_CNT. Checks read keyboard state against @key_down_arr
+ * and updates @key_change_arr array. The @key_down_arr state is 
+ * left unchanged. It is changed later by kbd_down() function.
+ * Returns 0, if no keyboard activity is found. Returns 1
+ * if at least one key is pressed. Returns 2 or 3 in case
+ * of detected change.
+ */
+int 
+kbd_scan()
+{
+       int i, ret=0;
+       unsigned char mask, val, chng;
+       for(i=0,mask=1;i<KBD_SCAN_CNT;i++,mask<<=1) {
+               val=kbd_onerow(mask);
+               chng=val^key_down_arr[i];
+               key_chng_arr[i]=chng;
+               if(val) ret|=1;
+               if(chng) ret|=2;
+       }
+       /* mx1_kbd_onerow(~0); */
+       return ret;
+}
+
+
+/**
+ * kbd_scan2mod - Propagate keyboard matrix changes between modifiers
+ * @scan_code:         Scan code of last detected key change
+ *
+ * Functions check keyboard matrix state in @key_down_arr.
+ * It updates @key_mod according to @key_down_arr and 
+ * modifiers transformations table @kbd_scan2mwmod_tab.
+ */
+void 
+kbd_scan2mod(int scan_code)
+{
+       unsigned char val, chng;
+       int s;
+       scan2mod_t *mt=kbd_scan2mod_tab;
+
+       for(;(s=mt->scan);mt++) {
+               chng=(s==scan_code);
+               s--;
+               val=key_down_arr[s/KBD_RET_CNT]&(1<<(s%KBD_RET_CNT));
+               if(val) {
+                       key_mod|=mt->set_mod;
+                       if(chng){
+                               key_mod^=mt->xor_mod;
+                       }
+               } else {
+                       key_mod&=~mt->set_mod;
+               }
+       }
+}
+
+/**
+ * kbd_down - Detects changed key scancode and applies changes to matrix state
+ *
+ * Functions check @key_chng_arr and process changes.
+ * It updates its internal state @key_state, does
+ * noise cancellation and repeat timing, then updates 
+ * @key_down_arr, stores detected scancode to @key_last_changed
+ * and calls modifiers processing kbd_scan2mod().
+ * Return value is zero if no change is detected. 
+ * In other case evaluated scancode is returned.
+ * Variable @key_hit signals by value 1 pressed key, by value
+ * 2 key release.
+ */
+int 
+kbd_down()
+{
+       int i, j=0;
+       unsigned char val;
+       
+        if(!(key_state&KEY_STATE_BUSY)){
+               for(i=0;i<KBD_SCAN_CNT;i++) {
+                       if(!(val=key_chng_arr[i])) continue;
+                       for(j=0;!(val&1);j++) val>>=1;
+                       key_last_changed=i*KBD_RET_CNT+j+1;
+                       if(key_down_arr[i]&(1<<j)){
+                               key_time=KEY_TIMER+KEY_PUSH_T;
+                               key_state=KEY_STATE_RELEASE;
+                       }else{
+                               key_time=KEY_TIMER+KEY_RELEASE_T;
+                               key_state=KEY_STATE_PUSH;
+                       }
+                       break;
+               }
+               if(key_state==KEY_STATE_IDLE)
+                       return 0;
+       } else {
+               if(!key_last_changed){
+                       key_state=KEY_STATE_IDLE;
+                       return 0;
+               }
+               i=(key_last_changed-1)/KBD_RET_CNT;
+               j=(key_last_changed-1)%KBD_RET_CNT;
+               if(!(key_chng_arr[i]&(1<<j))){
+                       /* Noise detected */
+                       if(!(key_state&KEY_STATE_NOISE)){
+                               key_time=KEY_TIMER+KEY_RELEASE_T;
+                               key_state|=KEY_STATE_NOISE;
+                       }
+               }
+       }
+
+       if(!key_use_timer){
+               if(KEY_TIMER) key_use_timer=1;
+               if(key_state&KEY_STATE_REPEAT) return 0;
+       }else{
+               if((long)(KEY_TIMER-key_time)<0) return 0;
+       }
+       
+       if(key_state==KEY_STATE_PUSH) {
+               key_down_arr[i]|=1<<j;
+               kbd_scan2mod(key_last_changed);
+               key_state=KEY_STATE_REPEAT;
+               key_time=KEY_TIMER+KEY_REPFIRST_T;
+               key_hit=1;
+               return key_last_changed;
+       } else if(key_state==KEY_STATE_REPEAT) {
+               key_time=KEY_TIMER+KEY_REPNEXT_T;
+               key_hit=1;
+               return key_last_changed;
+       } else if(key_state==KEY_STATE_RELEASE) {
+               key_down_arr[i]&=~(1<<j);
+               kbd_scan2mod(key_last_changed);
+               key_state=KEY_STATE_IDLE;
+               key_hit=2;
+               return key_last_changed;
+       } 
+       key_state=KEY_STATE_IDLE;
+       return 0;
+}
+
+/**
+ * kbd_scan2key - Converts scancode to kbd_key_t keyboard values
+ * @scan:      Detected scancode
+ *
+ * Computes kbd_key_t value for detected scancode.
+ * Uses @kbd_scan2key_tab transformation table
+ * and @key_mod modifiers information.
+ */
+kbd_key_t kbd_scan2key(int scan)
+{
+       if((key_mod&KBDMOD_SGM_SC)&&kbd_scan2key_tab[scan].sc)
+               return kbd_scan2key_tab[scan].sc;
+       return kbd_scan2key_tab[scan].bc;
+}
+
diff --git a/embedded/libs4c/kbd/kbd_dev_ops.c b/embedded/libs4c/kbd/kbd_dev_ops.c
new file mode 100644 (file)
index 0000000..1eb3776
--- /dev/null
@@ -0,0 +1,103 @@
+#include <string.h>
+#include "kbd.h"
+
+#ifdef _DEVICE_H
+/* create the microwindows keyboard device */
+
+KBDDEVICE kbddev = {
+       kbd_Open,
+       kbd_Close,
+       kbd_GetModifierInfo,
+       kbd_Read,
+       kbd_Poll
+};
+#endif /* _DEVICE_H */
+
+/**
+ * kbd_Open - Open the keyboard
+ * @pkd:       Pointer to keyboard device
+ */
+int
+kbd_Open(KBDDEVICE *pkd)
+{
+       key_last_changed=0;
+       key_mod=0;
+       key_hit=0;
+       key_use_timer=0;
+       memset(key_down_arr,0,sizeof(key_down_arr));
+       kbd_setio();
+       return 1;
+}
+
+/**
+ * mx1_kbd_Close - Closes keyboard
+ */
+void
+kbd_Close(void)
+{
+}
+
+/**
+ * mx1_kbd_Poll - Polls for keyboard events
+ *
+ * Returns non-zero value if change is detected.
+ */
+int
+kbd_Poll(void)
+{
+       if(key_hit)
+               return 1;
+       if(kbd_scan())
+               kbd_down();
+       return key_hit?1:0;
+}
+
+/**
+ * kbd_GetModifierInfo - Returns the possible modifiers for the keyboard
+ * @modifiers:         If non-NULL, ones in defined modifiers bits are returned.
+ * @curmodifiers:      If non-NULL, ones in actually active modifiers
+ *                     bits are returned.
+ */
+void
+kbd_GetModifierInfo(kbd_keymod_t *modifiers, kbd_keymod_t *curmodifiers)
+{
+       if (modifiers)
+               *modifiers = 0;         /* no modifiers available */
+       if (curmodifiers)
+               *curmodifiers = key_mod&~KBDMOD_SGM_SC;
+}
+
+/**
+ * mx1_kbd_Read - Reads resolved MWKEY value, modifiers and scancode
+ * @buf:               If non-NULL, resolved MWKEY is stored here
+ * @modifiers:         If non-NULL, ones in actually active modifiers
+ *                     bits are returned
+ * @scancode:          If non-NULL, scancode of resolved key is stored
+ *                     here
+ *
+ * This function reads one keystroke from the keyboard, and the current state
+ * of the modifier keys (ALT, SHIFT, etc).  Returns -1 on error, 0 if no data
+ * is ready, 1 on a keypress, and 2 on keyrelease.
+ * This is a non-blocking call.
+ */
+int
+kbd_Read(kbd_key_t *buf, kbd_keymod_t *modifiers, kbd_scan_code_t *scancode)
+{
+        int ret;
+       if(!key_hit) {
+               if(kbd_scan()){
+                       kbd_down();
+               }
+       }
+       if(modifiers)
+               *modifiers = key_mod&~KBDMOD_SGM_SC;
+       if(!key_hit)
+               return 0;
+       if(scancode)
+               *scancode = key_last_changed;
+       if(buf)
+               *buf = kbd_scan2key(key_last_changed);
+       ret=key_hit;
+       key_hit=0;
+       return ret;
+}
diff --git a/embedded/libs4c/keyval/Makefile b/embedded/libs4c/keyval/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/libs4c/keyval/Makefile.omk b/embedded/libs4c/keyval/Makefile.omk
new file mode 100644 (file)
index 0000000..36743e7
--- /dev/null
@@ -0,0 +1,9 @@
+# -*- makefile -*-
+
+default_CONFIG = CONFIG_KEYVAL=n
+
+ifeq ($(CONFIG_KEYVAL),y) 
+lib_LIBRARIES = keyval
+include_HEADERS += keyvalpb.h keyval_id.h
+keyval_SOURCES += keyvalpb.c 
+endif #CONFIG_KEYVAL
diff --git a/embedded/libs4c/keyval/keyval_id.h b/embedded/libs4c/keyval/keyval_id.h
new file mode 100644 (file)
index 0000000..60641d2
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _KEYVAL_ID_H_
+#define _KEYVAL_ID_H_
+
+#include "keyvalpb.h"
+
+#define KVPB_KEYID_ULAN_ADDR            0x10
+#define KVPB_KEYID_ULAN_SN              0x11
+
+#define KVPB_KEYID_HIS_ACCESS_CODE     0x20
+
+#endif /* _KEYVAL_ID_H_ */
+
diff --git a/embedded/libs4c/keyval/keyvalpb.c b/embedded/libs4c/keyval/keyvalpb.c
new file mode 100644 (file)
index 0000000..8dd6d1e
--- /dev/null
@@ -0,0 +1,494 @@
+/*******************************************************************
+  Key Value Persistent Storage
+
+  keyvalpb.c   - key value parameters block
+
+  (C) Copyright 2003-2005 by Pavel Pisa - Originator
+  (C) Copyright 2004-2005 by Petr Smolik - Originator
+
+  The uLan utilities library can be used, copied and modified under
+  next licenses
+    - GPL - GNU General Public License
+    - LGPL - GNU Lesser General Public License
+    - MPL - Mozilla Public License
+    - and other licenses added by project originators
+  Code can be modified and re-distributed under any combination
+  of the above listed licenses. If contributor does not agree with
+  some of the licenses, he/she can delete appropriate line.
+  Warning, if you delete all lines, you are not allowed to
+  distribute source code and/or binaries utilizing code.
+  
+  See files COPYING and README for details.
+
+ *******************************************************************/
+
+#include <string.h>
+#include "keyvalpb.h"
+
+/*
+ * kvpb_memsum - Compute checksum of given memory area
+ * @base: Pointer to the base of of the region
+ * @size: Size of utilized part of the region
+ *
+ * Return Value: Computed checksum value
+ * File: keyvalpb.c
+ */
+kvpb_sum_t kvpb_memsum(KVPB_DPTRTYPE uint8_t *base, kvpb_size_t size)
+{
+  KVPB_LOCALDATA kvpb_sum_t sum=0;
+  KVPB_DPTRTYPE uint16_t *p=(KVPB_DPTRTYPE uint16_t *)base;
+  size=(size+1)>>1;
+  while(size--){
+    sum+=*(p++);
+  }
+  sum&=KVPB_SUM_MASK;
+  sum|=KVPB_SUM_OKVAL;
+  return sum;
+}
+
+#ifndef KVPB_WITHOUT_HADLE
+/*
+ * kvpb_get_psum - Get pointer to the region check sum
+ * @kvpb_block: Pointer to the KVPB access information/state structure
+ * @base: Pointer to the base of of the region
+ * @size: Size of one data block region
+ *
+ * Return Value: Pointer to the actual region check sum placement
+ * File: keyvalpb.c
+ */
+KVPB_DPTRTYPE kvpb_sum_t *kvpb_get_psum(kvpb_block_t *kvpb_block,
+                                  KVPB_DPTRTYPE uint8_t *base, kvpb_size_t size) 
+#else
+KVPB_DPTRTYPE kvpb_sum_t *__kvpb_get_psum(
+                                  KVPB_DPTRTYPE uint8_t *base, kvpb_size_t size) 
+#endif
+{
+  KVPB_DPTRTYPE kvpb_sum_t *psum;
+  psum=kvpb_psum_align(kvpb_block,(KVPB_DPTRTYPE kvpb_sum_t*)(base+size)-1);
+  while((KVPB_DPTRTYPE uint8_t*)psum>=base) {
+    if (*kvpb_psum_valid_loc(kvpb_block,psum)!=0) 
+      return psum;
+    psum=kvpb_psum_align(kvpb_block,psum-1);
+  }
+  return NULL;
+}
+
+#ifndef KVPB_WITHOUT_HADLE
+/*
+ * kvpb_get_cfk - Get space where to place new key-value pair
+ * @kvpb_block: Pointer to the KVPB access information/state structure
+ * @mode: 0 .. work on active/valid data region;
+ *     1 .. work on the first copy/region, 2 .. work on the second copy/region
+ * @size: Size of required space for stored value
+ *
+ * Return Value: Pointer where next pair should be stored or %NULL
+ * File: keyvalpb.c
+ */
+KVPB_DPTRTYPE kvpb_key_t *kvpb_get_cfk(kvpb_block_t *kvpb_block,uint8_t mode,int size)
+#else
+KVPB_DPTRTYPE kvpb_key_t *__kvpb_get_cfk(uint8_t mode,int size)
+#endif
+{
+  KVPB_DPTRTYPE kvpb_sum_t *psum;
+  KVPB_DPTRTYPE uint8_t    *p;
+  KVPB_DPTRTYPE uint8_t    *r;
+  p=kvpb_region_base(kvpb_block,0);
+  size=kvpb_chunk_align(kvpb_block,size+sizeof(kvpb_key_t))+
+       (kvpb_block->flags&KVPB_DESC_CHUNKWO?kvpb_chunk_size(kvpb_block):0);
+  psum=kvpb_block->psum1;
+  if((!mode && (kvpb_block->flags & KVPB_DESC_USE2ND))||(mode==2)) {
+    if(!(kvpb_block->flags&KVPB_DESC_DOUBLE))
+      return NULL;
+    p=kvpb_region_base(kvpb_block,1);
+    psum=kvpb_block->psum2;
+  }
+  do {
+    kvpb_size_t ksize=((KVPB_DPTRTYPE kvpb_key_t *)p)->size;
+    if(ksize==KVPB_EMPTY)
+      break;
+    if(((uint8_t*)psum-(uint8_t*)p)<ksize)
+      return NULL;
+    p+=kvpb_chunk_align(kvpb_block,ksize+sizeof(kvpb_key_t))+
+       (kvpb_block->flags&KVPB_DESC_CHUNKWO?kvpb_chunk_size(kvpb_block):0);
+  } while(1);
+  r=(KVPB_DPTRTYPE uint8_t*)p+size+sizeof(kvpb_key_t);
+  if(r<p)
+    return NULL;
+  if ((uint8_t*)kvpb_psum_align(kvpb_block,psum-1)<r) {
+    return NULL;
+  }
+  return (KVPB_DPTRTYPE kvpb_key_t*)p;
+}
+
+
+#ifndef KVPB_WITHOUT_HADLE
+/**
+ * kvpb_check - Check data consistency of the KVPB storage
+ * @kvpb_block: Pointer to the KVPB access information/state structure
+ * @mode: if mode is nonzero, try to restore valid state or erase all data
+ *
+ * Return Value: 0 .. all regions are correct, 1 .. the first region is valid, the second
+ *     region is invalid or has been updated if @mode has been set, 2 .. the second region
+ *     is valid, the first is invalid or has been updated if @mode has been set, 3 .. both
+ *     regions has been erased and emptied, -1 .. the state is inconsistent and no valid
+ *     region has been found and state has not be corrected
+ * File: keyvalpb.c
+ */
+int kvpb_check(kvpb_block_t *kvpb_block, uint8_t mode)
+#else
+int __kvpb_check(uint8_t mode)
+#endif
+{
+  KVPB_DPTRTYPE uint8_t *p;
+  KVPB_LOCALDATA int ret=-1;
+  KVPB_LOCALDATA kvpb_sum_t sum;
+  
+  kvpb_block->flags&=~KVPB_DESC_USE2ND;
+  
+  p=kvpb_region_base(kvpb_block,0);
+  kvpb_block->psum1=kvpb_get_psum(kvpb_block,p,kvpb_block->size);
+  if (kvpb_block->psum1) {
+    sum=kvpb_memsum(p,(KVPB_DPTRTYPE uint8_t*)kvpb_block->psum1-p);
+    if(*kvpb_block->psum1==sum){
+      ret=1;
+    }
+  }
+
+  if(kvpb_block->flags&KVPB_DESC_DOUBLE){
+    p=kvpb_region_base(kvpb_block,1);
+    kvpb_block->psum2=kvpb_get_psum(kvpb_block,p,kvpb_block->size);
+    if (kvpb_block->psum2) {
+      sum=kvpb_memsum(p,(KVPB_DPTRTYPE uint8_t*)kvpb_block->psum2-p);
+      if(*kvpb_block->psum2==sum) {
+        if(ret>=0){
+          ret=0;
+        } else {
+          ret=2;
+          kvpb_block->flags|=KVPB_DESC_USE2ND;
+        }
+      }
+    }
+  } else {
+    if(ret>=0)
+      ret=0;
+  }
+  
+  if(ret){
+    if(!mode) {
+      kvpb_block->flags|=KVPB_DESC_RO;
+    } else {
+      /* correct for FLASH */
+      if(ret<0){
+        p=kvpb_region_base(kvpb_block,0);
+        kvpb_block_erase(kvpb_block,p,kvpb_block->size);
+        kvpb_block->psum1=kvpb_psum_align(kvpb_block,(KVPB_DPTRTYPE kvpb_sum_t*)(p+kvpb_block->size)-1);
+        sum=kvpb_memsum(p,(KVPB_DPTRTYPE uint8_t*)kvpb_block->psum1-p);
+       kvpb_block_copy(kvpb_block,kvpb_block->psum1,&sum,sizeof(kvpb_sum_t));
+       if(kvpb_block->flags&KVPB_DESC_DOUBLE){
+          p=kvpb_region_base(kvpb_block,1);
+          kvpb_block_erase(kvpb_block,p,kvpb_block->size);
+          kvpb_block->psum2=kvpb_psum_align(kvpb_block,(KVPB_DPTRTYPE kvpb_sum_t*)(p+kvpb_block->size)-1);
+          sum=kvpb_memsum(p,(KVPB_DPTRTYPE uint8_t*)kvpb_block->psum2-p);
+          kvpb_block_copy(kvpb_block,kvpb_block->psum2,&sum,sizeof(kvpb_sum_t));
+       }
+       ret=3;
+      }else{
+        if(ret==1){
+          kvpb_block_erase(kvpb_block,kvpb_region_base(kvpb_block,1),kvpb_block->size);
+          kvpb_block_copy(kvpb_block,kvpb_region_base(kvpb_block,1),
+                         kvpb_region_base(kvpb_block,0),kvpb_block->size);
+
+       }else{
+          kvpb_block_erase(kvpb_block,kvpb_region_base(kvpb_block,0),kvpb_block->size);
+          kvpb_block_copy(kvpb_block,kvpb_region_base(kvpb_block,0),
+                         kvpb_region_base(kvpb_block,1),kvpb_block->size);
+       }
+      }
+      kvpb_block->flags&=~KVPB_DESC_RO;
+    }
+  }
+  kvpb_block_flush(kvpb_block); 
+  if(ret>=0) kvpb_block->flags|=KVPB_DESC_VALID;
+  return ret;
+}
+
+#ifndef KVPB_WITHOUT_HADLE
+/**
+ * kvpb_first - Get pointer to the first key-value pair in the KVPB storage
+ * @kvpb_block: Pointer to the KVPB access information/state structure
+ * @mode: 0 .. iterate over active/valid data region;
+ *     1 .. iterate over first copy/region, 2 .. iterate over second copy/region
+ *
+ * Return Value: Pointer to the first key-value pair
+ *     or %NULL if no pair exist.
+ * File: keyvalpb.c
+ */
+KVPB_DPTRTYPE kvpb_key_t *kvpb_first(kvpb_block_t *kvpb_block, uint8_t mode)
+#else
+KVPB_DPTRTYPE kvpb_key_t *__kvpb_first(uint8_t mode)
+#endif
+{
+  KVPB_DPTRTYPE kvpb_key_t *key=(KVPB_DPTRTYPE kvpb_key_t *)kvpb_region_base(kvpb_block,0);
+  if((!mode && (kvpb_block->flags & KVPB_DESC_USE2ND))||(mode==2)) {
+    if(!(kvpb_block->flags&KVPB_DESC_DOUBLE))
+      return NULL;
+    key=(KVPB_DPTRTYPE kvpb_key_t *)kvpb_region_base(kvpb_block,1);
+  }
+  while(*kvpb_keyid_valid(kvpb_block,key)==KVPB_KEYID_INVALID) {
+    key=kvpb_next(kvpb_block,key);
+    if (!key) 
+      return NULL;
+  }
+  return key->size!=KVPB_EMPTY?key:NULL;
+}
+
+#ifndef KVPB_WITHOUT_HADLE
+/**
+ * kvpb_next - Iterate to the next consecutive key-value pair
+ * @kvpb_block: Pointer to the KVPB access information/state structure
+ * @key: Pointer to the previous key-value pair
+ *
+ * Return Value: Pointer to the next key-value pair
+ *     or %NULL if no/no-more pairs exist.
+ * File: keyvalpb.c
+ */
+KVPB_DPTRTYPE kvpb_key_t *kvpb_next(kvpb_block_t *kvpb_block, KVPB_DPTRTYPE kvpb_key_t *key)
+#else
+KVPB_DPTRTYPE kvpb_key_t *__kvpb_next(KVPB_DPTRTYPE kvpb_key_t *key)
+#endif
+{
+  do {
+    key=(KVPB_DPTRTYPE kvpb_key_t *)((KVPB_DPTRTYPE uint8_t *)key+
+                               kvpb_chunk_align(kvpb_block,key->size+sizeof(kvpb_key_t))+
+                               (kvpb_block->flags&KVPB_DESC_CHUNKWO?kvpb_chunk_size(kvpb_block):0));
+    if (key->size==KVPB_EMPTY) return NULL;
+  } while(*kvpb_keyid_valid(kvpb_block,key)==KVPB_KEYID_INVALID);
+  return key;
+}
+
+#ifndef KVPB_WITHOUT_HADLE
+/**
+ * kvpb_find - Find first of occurrence of given key ID
+ * @kvpb_block: Pointer to the KVPB access information/state structure
+ * @keyid: Ordinal value representing key ID
+ * @mode: iteration mode modifier: 0 .. search in the active/valid data region;
+ *     1 .. search in the first copy/region, 2 .. search in the second copy/region
+ * @key: Previous key occurrence pointer or %NULL value to find first key ID named key-value pair
+ *
+ * Return Value: Pointer to the first on subsequent occurrence of key-value pair addressed by given key ID
+ *     or %NULL if no/no-more occurrences exists.
+ * File: keyvalpb.c
+ */
+KVPB_DPTRTYPE kvpb_key_t *kvpb_find(kvpb_block_t *kvpb_block, kvpb_keyid_t keyid, uint8_t mode, KVPB_DPTRTYPE kvpb_key_t *key)
+#else
+KVPB_DPTRTYPE kvpb_key_t *__kvpb_find(kvpb_keyid_t keyid, uint8_t mode, KVPB_DPTRTYPE kvpb_key_t *key)
+#endif
+{
+  if(!(kvpb_block->flags&KVPB_DESC_VALID))
+    return NULL;
+  if (key) {
+      key=kvpb_next(kvpb_block, key);
+  } else {
+      key=kvpb_first(kvpb_block, mode);
+  }
+  while(key) {
+    if((key->keyid==keyid) || (keyid==0))
+      return key;
+    key=kvpb_next(kvpb_block, key);
+  }
+  return key;
+}
+
+#ifndef KVPB_WITHOUT_HADLE
+/**
+ * kvpb_compact_region - Compact one KVPB data block/region
+ * @kvpb_block: Pointer to the KVPB access information/state structure
+ * @keyid: Key ID which should be omitted from compacted data
+ * @mode: 0 .. compact active/valid data region;
+ *     1 .. compact the first data copy, 2 .. compact the second copy
+ *
+ * Return Value: Operation cannot be finished.
+ * File: keyvalpb.c
+ */
+int kvpb_compact_region(kvpb_block_t *kvpb_block, uint8_t mode, kvpb_keyid_t keyid) 
+#else
+int __kvpb_compact_region(uint8_t mode, kvpb_keyid_t keyid) 
+#endif
+{
+  KVPB_DPTRTYPE uint8_t *p;
+  KVPB_DPTRTYPE kvpb_key_t *des,*src;
+
+  p=kvpb_region_base(kvpb_block,0);
+  src=(KVPB_DPTRTYPE kvpb_key_t*)kvpb_region_base(kvpb_block,1);
+  des=(KVPB_DPTRTYPE kvpb_key_t*)p;
+  kvpb_block->psum1=kvpb_psum_align(kvpb_block,
+                    (KVPB_DPTRTYPE kvpb_sum_t*)(kvpb_region_base(kvpb_block,1))-1);
+  if((!mode && (kvpb_block->flags & KVPB_DESC_USE2ND))||(mode==2)) {
+    if(!(kvpb_block->flags&KVPB_DESC_DOUBLE))
+      return -1;
+    src=(KVPB_DPTRTYPE kvpb_key_t*)p;
+    des=(KVPB_DPTRTYPE kvpb_key_t*)kvpb_region_base(kvpb_block,1);
+    kvpb_block->psum2=kvpb_psum_align(kvpb_block,
+                      (KVPB_DPTRTYPE kvpb_sum_t*)(kvpb_region_base(kvpb_block,2))-1);
+  }
+  kvpb_block_flush(kvpb_block);
+  kvpb_block_erase(kvpb_block,des,kvpb_block->size);
+  while(src) {
+    int s=kvpb_chunk_align(kvpb_block,src->size+sizeof(kvpb_key_t));
+    if((*kvpb_keyid_valid(kvpb_block,src)!=KVPB_KEYID_INVALID) && (src->keyid!=keyid)) {
+      kvpb_block_copy(kvpb_block,des,src,s);    
+      if (kvpb_block->flags&KVPB_DESC_CHUNKWO) s+=kvpb_chunk_size(kvpb_block);
+      des=(KVPB_DPTRTYPE kvpb_key_t*)((uint8_t*)des+s);
+    }
+    src=kvpb_next(kvpb_block, src);
+  }
+  kvpb_block_flush(kvpb_block);
+  return 0;
+}
+
+#ifndef KVPB_WITHOUT_HADLE
+/**
+ * kvpb_get_key - Get value for given key ID
+ * @kvpb_block: Pointer to the KVPB access information/state structure
+ * @keyid: Ordinal value representing key ID
+ * @size: The size of the buffer provided to store data into
+ * @buf: Pointer to the buffer, where retrieved data should be copied
+ *
+ * Return Value: Number of retrieved value bytes if operation is successful
+ *     or -1 if there is no such key ID or operation fails for other reason.
+ * File: keyvalpb.c
+ */
+int kvpb_get_key(kvpb_block_t *kvpb_block, kvpb_keyid_t keyid, kvpb_size_t size, void *buf)
+#else
+int __kvpb_get_key(kvpb_keyid_t keyid, kvpb_size_t size, void *buf)
+#endif
+{
+  KVPB_DPTRTYPE kvpb_key_t *key;
+  key=kvpb_find(kvpb_block,keyid,0,NULL);
+  if(!key) return -1;
+  if(size && buf){
+    if(key->size<size)
+      size=key->size;
+    memcpy(buf,key+1,size);
+  }
+  return key->size;
+}
+
+
+#ifndef KVPB_WITHOUT_HADLE
+/**
+ * kvpb_set_key - Set new value or define new key-value pair
+ * @kvpb_block: Pointer to the KVPB access information/state structure
+ * @keyid: Ordinal value representing key ID, if or-red with %KVPB_KEYID_DUPLIC,
+ *     the key ID can be defined/inserted  multiple times
+ * @size: Stored value size in bytes
+ * @buf: Pointer to the stored value data
+ *
+ * Return Value: Number of stored bytes (equal to @size) if operation is successful
+ *     or -1 if operation fails.
+ * File: keyvalpb.c
+ */
+int kvpb_set_key(kvpb_block_t *kvpb_block, kvpb_keyid_t keyid, kvpb_size_t size, const void *buf)
+#else
+int __kvpb_set_key(kvpb_keyid_t keyid, kvpb_size_t size, const void *buf)
+#endif
+{
+  KVPB_LOCALDATA kvpb_sum_t sum;
+  KVPB_DPTRTYPE kvpb_sum_t *psum;
+  KVPB_DPTRTYPE kvpb_key_t *key;
+  KVPB_DPTRTYPE uint8_t *p;
+  
+  if(!(kvpb_block->flags&KVPB_DESC_VALID))
+    return -1;
+  if(kvpb_block->flags&KVPB_DESC_RO)
+    return -1;
+  
+  /*first region*/
+  psum=kvpb_psum_align(kvpb_block,kvpb_block->psum1);
+  sum=0;
+  kvpb_block_copy(kvpb_block,kvpb_psum_valid_loc(kvpb_block,psum),&sum,sizeof(kvpb_sum_t));
+  kvpb_block->psum1=kvpb_psum_align(kvpb_block,kvpb_block->psum1-1);
+  if (!(keyid&KVPB_KEYID_DUPLIC) || !buf) {
+    kvpb_each_from(kvpb_block,keyid,1,key) {
+      kvpb_keyid_t dkeyid=KVPB_KEYID_INVALID;
+      kvpb_block_copy(kvpb_block,kvpb_keyid_valid(kvpb_block,key),&dkeyid,sizeof(kvpb_keyid_t));
+    }
+  }
+  key=kvpb_get_cfk(kvpb_block,1,size);
+  if (!key) {
+    kvpb_compact_region(kvpb_block,1,(keyid&KVPB_KEYID_DUPLIC)?0:keyid);
+    key=kvpb_get_cfk(kvpb_block,1,size);
+  }
+  if (keyid && key && buf) {
+    kvpb_block_copy(kvpb_block,&key->size,&size,sizeof(kvpb_size_t));
+    kvpb_block_copy(kvpb_block,&key->keyid,&keyid,sizeof(kvpb_keyid_t));
+    kvpb_block_copy(kvpb_block,(uint8_t*)(key+1),buf,/*align???*/ size);
+  }
+  /* need flush data to count correct value of new check sum */
+  kvpb_block_flush(kvpb_block);
+
+  p=kvpb_region_base(kvpb_block,0);
+  sum=kvpb_memsum(p,(KVPB_DPTRTYPE uint8_t*)kvpb_block->psum1-p);
+  kvpb_block_copy(kvpb_block,kvpb_block->psum1,&sum,sizeof(kvpb_sum_t));  
+  kvpb_block_flush(kvpb_block);
+  if(!(kvpb_block->flags&KVPB_DESC_DOUBLE))
+     return key?size:-1;
+
+  /*Write in the first region failed, switching to backup region */
+  if(kvpb_block->flags&KVPB_DESC_RO){
+    kvpb_block->flags|=KVPB_DESC_USE2ND;
+    return -1;
+  }
+
+  /*second region*/
+  psum=kvpb_psum_align(kvpb_block,kvpb_block->psum2);
+  sum=0;
+  kvpb_block_copy(kvpb_block,kvpb_psum_valid_loc(kvpb_block,psum),&sum,sizeof(kvpb_sum_t));
+  kvpb_block->psum2=kvpb_psum_align(kvpb_block,kvpb_block->psum2-1);
+  if (!(keyid&KVPB_KEYID_DUPLIC) || !buf) {
+    kvpb_each_from(kvpb_block,keyid,2,key) {
+      kvpb_keyid_t dkeyid=KVPB_KEYID_INVALID;
+      kvpb_block_copy(kvpb_block,kvpb_keyid_valid(kvpb_block,key),&dkeyid,sizeof(kvpb_keyid_t));
+    }
+  }
+  key=kvpb_get_cfk(kvpb_block,2,size);
+  if (!key) {
+    kvpb_compact_region(kvpb_block,2,(keyid&KVPB_KEYID_DUPLIC)?0:keyid);
+    key=kvpb_get_cfk(kvpb_block,2,size);
+  }
+  if (keyid && key && buf) {
+    kvpb_block_copy(kvpb_block,&key->size,&size,sizeof(kvpb_size_t));
+    kvpb_block_copy(kvpb_block,&key->keyid,&keyid,sizeof(kvpb_keyid_t));
+    kvpb_block_copy(kvpb_block,(uint8_t*)(key+1),buf,/*align???*/ size);
+  }
+  kvpb_block_flush(kvpb_block);
+        
+  p=kvpb_region_base(kvpb_block,1);
+  sum=kvpb_memsum(p,(KVPB_DPTRTYPE uint8_t*)kvpb_block->psum2-p);
+  kvpb_block_copy(kvpb_block,kvpb_block->psum2,&sum,sizeof(kvpb_sum_t));
+  kvpb_block_flush(kvpb_block);
+  /*Write in the second region failed, switching to the first region */
+  if(kvpb_block->flags&KVPB_DESC_RO){
+    kvpb_block->flags&=~KVPB_DESC_USE2ND;
+    return -1;
+  }
+
+  return key?size:-1;
+}
+
+#ifndef KVPB_MINIMALIZED
+/**
+ * kvpb_err_keys - Erase/delete key-value pair
+ * @kvpb_block: Pointer to the KVPB access information/state structure
+ * @keyid: Ordinal value representing key ID
+ *
+ * Return Value: Positive or zero value informs about successful operation,
+ *     -1 if operation fails.
+ * File: keyvalpb.c
+ */
+int kvpb_err_keys(kvpb_block_t *kvpb_block, kvpb_keyid_t keyid)
+{
+  return kvpb_set_key(kvpb_block,keyid,0,NULL);
+}
+#endif  /*KVPB_MINIMALIZED*/
+
diff --git a/embedded/libs4c/keyval/keyvalpb.h b/embedded/libs4c/keyval/keyvalpb.h
new file mode 100644 (file)
index 0000000..dbb7774
--- /dev/null
@@ -0,0 +1,327 @@
+/*******************************************************************
+  Key Value Persistent Storage
+
+  keyvalpb.h   - key value parameters block
+
+  (C) Copyright 2003-2005 by Pavel Pisa - Originator
+  (C) Copyright 2004-2005 by Petr Smolik - Originator
+
+  The uLan utilities library can be used, copied and modified under
+  next licenses
+    - GPL - GNU General Public License
+    - LGPL - GNU Lesser General Public License
+    - MPL - Mozilla Public License
+    - and other licenses added by project originators
+  Code can be modified and re-distributed under any combination
+  of the above listed licenses. If contributor does not agree with
+  some of the licenses, he/she can delete appropriate line.
+  Warning, if you delete all lines, you are not allowed to
+  distribute source code and/or binaries utilizing code.
+  
+  See files COPYING and README for details.
+
+ *******************************************************************/
+
+#ifndef _KEYVALPB_H_
+#define _KEYVALPB_H_
+
+//#include <inttypes.h>
+#include <types.h>
+#include <system_def.h>
+#include <cpu_def.h>
+
+#ifdef  KVPB_MINIMALIZED
+#define KVPB_WITHOUT_HADLE
+#define KVPB_DPTRTYPE  CODE
+#define KVPB_LOCALDATA DATA
+#endif  /*KVPB_MINIMALIZED*/
+
+#ifndef KVPB_DPTRTYPE
+#define KVPB_DPTRTYPE
+#endif  /*KVPB_DPTRTYPE*/
+
+#ifndef KVPB_LOCALDATA
+#define KVPB_LOCALDATA
+#endif  /*KVPB_DPTRTYPE*/
+
+#ifndef KVPB_BLOCK_LOC
+#define KVPB_BLOCK_LOC
+#endif  /*KVPB_BLOCK_LOC*/
+
+#define KVPB_EMPTY         ((kvpb_size_t)~0)
+
+#define KVPB_KEYID_INVALID      0
+#define KVPB_KEYID_DUPLIC       ((((kvpb_keyid_t)~0)>>1)+1)
+#define KBPB_KEYID_INVALID_BIT  (KVPB_KEYID_DUPLIC>>1)
+
+#define KVPB_SUM_MASK      (((kvpb_sum_t)~0)>>2)
+#define KVPB_SUM_OKVAL     (KVPB_SUM_MASK+1)
+
+#define KVPB_DESC_DOUBLE  0x01
+#define KVPB_DESC_USE2ND  0x02
+#define KVPB_DESC_VALID   0x04
+#define KVPB_DESC_RO      0x08
+#define KVPB_DESC_CHUNKWO 0x10
+#define KVPB_DESC_ALIGN4  0x40
+#define KVPB_DESC_FLASH   0x80  
+
+#ifdef  KVPB_MINIMALIZED
+typedef uint16_t kvpb_sum_t;
+typedef uint16_t kvpb_size_t;
+typedef uint8_t kvpb_keyid_t;
+#else  /*KVPB_MINIMALIZED*/
+typedef uint32_t kvpb_sum_t;
+typedef uint32_t kvpb_size_t;
+typedef uint32_t kvpb_keyid_t;
+#endif  /*KVPB_MINIMALIZED*/
+
+/**
+ * struct kvpb_block - Key-value parameter block access information
+ * @base: Pointer to the start of physically mapped key-value block data
+ * @size: Size of one region (one data copy) of parameter block
+ * @flags: Block state flags:
+ *     %KVPB_DESC_DOUBLE - the information is stored in two consecutive redundant copies/regions;
+ *     %KVPB_DESC_USE2ND - data will be read from the second copy because first one is damaged;
+ *     %KVPB_DESC_VALID - at least one region is valid;
+ *     %KVPB_DESC_RO - because of some problems, only read access is allowed
+ *      %KVPB_DESC_CHUNKWO - chunk can be written only once between erase operations 
+ *     %KVPB_DESC_ALIGN4 - data has to be aligned to four bytes
+ *     %KVPB_DESC_FLASH - flash memory is used for data storage
+ * @psum1: Pointer to the control checksum of the first data region
+ * @psum2: Pointer to the control checksum of the second data region
+ * @erase: Function to erase some range of the storage region
+ * @copy: Function to copy data into or between storage regions
+ * @flush: Function to finish pending copy operations
+ * @chunk_size: Minimal store chunk size which can be independently modified
+ *
+ * File: keyvalpb.h
+ */
+typedef struct kvpb_block {
+  KVPB_DPTRTYPE uint8_t *base;
+  kvpb_size_t size;
+  short flags;
+  KVPB_DPTRTYPE kvpb_sum_t *psum1;
+  KVPB_DPTRTYPE kvpb_sum_t *psum2;
+ #ifndef  KVPB_MINIMALIZED
+  int (*erase)(struct kvpb_block *store, void *base,int size);
+  int (*copy)(struct kvpb_block *store, void *des,const void *src,int len);
+  int (*flush)(struct kvpb_block *store);
+  unsigned chunk_size;
+ #endif  /* KVPB_MINIMALIZED */
+} kvpb_block_t;
+
+
+#define kvpb_region_base(block,regidx) (((block)->base+(regidx*(block)->size)))
+
+#ifndef  KVPB_MINIMALIZED
+ #ifndef kvpb_chunk_size
+   #define kvpb_chunk_size(store) ((store)->chunk_size<4?4:(store)->chunk_size)
+ #endif /*kvpb_chunk_size*/
+ #define kvpb_chunk_size_mask(store) (kvpb_chunk_size(store)-1)
+/**
+ * kvpb_chunk_align - Round up KVPB size to minimal store chunk size multiple
+ * @store: Pointer to the KVPB access information/state structure
+ * @size: Unaligned size
+ *
+ * Return Value: Minimal aligned size to hold unaligned size.
+ * File: keyvalpb.h
+ */
+ static inline unsigned kvpb_chunk_align(struct kvpb_block *store, unsigned size)
+ {
+   return ((size)+kvpb_chunk_size_mask(store))&~kvpb_chunk_size_mask(store);
+ }
+
+/**
+ * kvpb_psum_align - Round up KVPB size to minimal store chunk size multiple
+ * @store: Pointer to the KVPB access information/state structure
+ * @psum: Pointer to proposed location of next check sum location 
+ *
+ * Return Value: Pointer to next check sum location rounded down to next slot.
+ * File: keyvalpb.h
+ */
+ static inline kvpb_sum_t* kvpb_psum_align(struct kvpb_block *store, kvpb_sum_t *psum)
+ {
+   unsigned long mask=~kvpb_chunk_size_mask(store);
+   if(store->flags&KVPB_DESC_CHUNKWO)
+     mask<<=1;
+   return (kvpb_sum_t*)(((unsigned long)(psum))&mask);
+ }
+
+/**
+ * kvpb_psum_valid_loc - Return pointer to check sum validity info location
+ * @store: Pointer to the KVPB access information/state structure
+ * @psum: Pointer to corectly aligned check sum location
+ *
+ * Return Value: Pointer to location which indicates by zero value, that check sum
+ *               is invalidated.
+ * File: keyvalpb.h
+ */
+ static inline kvpb_sum_t* kvpb_psum_valid_loc(struct kvpb_block *store, kvpb_sum_t *psum)
+ {
+   if(!(store->flags&KVPB_DESC_CHUNKWO))
+     return psum;
+   else
+     return (kvpb_sum_t*)(((char *)(psum))+kvpb_chunk_size(store));
+ }
+
+/**
+ * kvpb_block_erase - Wrapper function to call KVPB specific data erase function
+ * @store: Pointer to the KVPB access information/state structure
+ * @base: Base address of erased region inside parameter block data region
+ * @size: Number of bytes to erase
+ *
+ * The KVPB mechanism is intended for FLASH type memories and it expect
+ * that only whole data region can be erased at time. The expected erase state
+ * is all bits set to the ones.
+ *
+ * Return Value: Negative value indicates operation fault.
+ * File: keyvalpb.h
+ */
+ static inline int kvpb_block_erase(struct kvpb_block *store, void *base,int size)
+ {
+   return store->erase(store, base,size) ; 
+ }
+
+/**
+ * kvpb_block_copy - Wrapper function to call KVPB specific data copy function
+ * @store: Pointer to the KVPB access information/state structure
+ * @des: Address of data destination pointing inside mapped parameter block data region
+ * @src: Address of data source pointing inside mapped parameter block data or RAM memory
+ * @len: Number of bytes to transfer
+ *
+ * Return Value: Negative value indicates operation fault.
+ * File: keyvalpb.h
+ */
+ static inline int kvpb_block_copy(struct kvpb_block *store, void *des,const void *src,int len)
+ {
+   return store->copy(store, des, src, len);
+ }
+
+/**
+ * kvpb_block_flush - Wrapper function to call KVPB specific flush function
+ * @store: Pointer to the KVPB access information/state structure
+ *
+ * Return Value: Negative value indicates operation fault.
+ * File: keyvalpb.h
+ */
+ static inline int kvpb_block_flush(struct kvpb_block *store)
+ {
+   if(!(store->flush)) return 0;
+   return store->flush(store);
+ }
+
+#else /* KVPB_MINIMALIZED */
+ #ifndef kvpb_chunk_size
+  #define kvpb_chunk_size(store) 1
+ #endif /*kvpb_chunk_size*/
+ #define kvpb_chunk_size_mask(store) (kvpb_chunk_size(store)-1)
+ #define kvpb_chunk_align(store,x) \
+               (((x)+kvpb_chunk_size_mask(store))&~kvpb_chunk_size_mask(store))
+ #define kvpb_psum_align(store,x) \
+                ((KVPB_DPTRTYPE kvpb_sum_t*)((unsigned)(x)&~kvpb_chunk_size_mask(store)))
+ #define kvpb_psum_valid_loc(store,x) \
+               ((kvpb_sum_t*)((char*)(x)+0*kvpb_chunk_size(store)))
+ #define kvpb_block_erase(store, base, size) flash_erase(base, size)
+ #define kvpb_block_copy(store, des, src, len) flash_copy(des, src, len) 
+ #define kvpb_block_flush(store) flash_flush() 
+ /* forward declarations for external procedures */
+ int flash_erase(void *base,int size);
+ int flash_copy(void *des,const void *src,int len);
+#ifndef flash_flush
+ int flash_flush(void);
+#endif /* flash_flush */
+#endif /* KVPB_MINIMALIZED */
+
+/**
+ * struct kvpb_key - Header of stored key value pair and structure for iteration over KVPB
+ * @size: Non-aligned byte size of the stored value
+ * @keyid: Ordinal value representing stored data key
+ *
+ * The header structure is followed by @size data bytes in the KVPB storage block.
+ * Because only word aligned write accesses are possible on some architectures
+ * and memory types the whole size of space occupied by one key-value pair is
+ * sum of rounded-up data size kvpb_chunk_align(@size)  and size of header sizeof(kvpb_key_t).
+ */
+typedef struct kvpb_key {
+  kvpb_size_t size;
+  kvpb_keyid_t keyid;
+} kvpb_key_t;
+
+#ifndef KVPB_WITHOUT_HADLE
+ static inline kvpb_keyid_t* kvpb_keyid_valid(struct kvpb_block *store, kvpb_key_t *key)
+ {
+   if(store->flags&KVPB_DESC_CHUNKWO)
+     return (kvpb_keyid_t*)((uint8_t*)key+(kvpb_chunk_align(store,key->size+sizeof(kvpb_key_t))));
+   return &(key->keyid);
+ }
+#else
+  #define kvpb_keyid_valid(store,key) (&((key)->keyid))
+#endif /*KVPB_WITHOUT_HADLE*/
+
+
+#ifndef KVPB_WITHOUT_HADLE
+KVPB_DPTRTYPE kvpb_key_t *kvpb_first(kvpb_block_t *block, uint8_t mode);
+KVPB_DPTRTYPE kvpb_key_t *kvpb_next(kvpb_block_t *block, KVPB_DPTRTYPE kvpb_key_t *key);
+KVPB_DPTRTYPE kvpb_key_t *kvpb_find(kvpb_block_t *block, kvpb_keyid_t keyid, uint8_t mode, KVPB_DPTRTYPE kvpb_key_t *key);
+int kvpb_get_key(kvpb_block_t *kvpb_block, kvpb_keyid_t keyid, kvpb_size_t size, void *buf);
+int kvpb_set_key(kvpb_block_t *kvpb_block, kvpb_keyid_t keyid, kvpb_size_t size, const void *buf);
+int kvpb_err_keys(kvpb_block_t *kvpb_block, kvpb_keyid_t keyid);
+int kvpb_check(kvpb_block_t *kvpb_block, uint8_t mode);
+#else
+extern KVPB_BLOCK_LOC kvpb_block_t kvpb_block_global;
+#define kvpb_block (&kvpb_block_global)
+KVPB_DPTRTYPE kvpb_sum_t *__kvpb_get_psum(KVPB_DPTRTYPE uint8_t *base, kvpb_size_t size);
+KVPB_DPTRTYPE kvpb_key_t *__kvpb_first(uint8_t mode);
+KVPB_DPTRTYPE kvpb_key_t *__kvpb_next(KVPB_DPTRTYPE kvpb_key_t *key);
+KVPB_DPTRTYPE kvpb_key_t *__kvpb_find(kvpb_keyid_t keyid, uint8_t mode, KVPB_DPTRTYPE kvpb_key_t *key);
+int __kvpb_get_key(kvpb_keyid_t keyid, kvpb_size_t size, void *buf);
+int __kvpb_set_key(kvpb_keyid_t keyid, kvpb_size_t size, const void *buf);
+int __kvpb_check(uint8_t mode);
+#define kvpb_get_psum(block, base, size) __kvpb_get_psum(base, size)
+#define kvpb_first(block, mode) __kvpb_first(mode)
+#define kvpb_next(block, key) __kvpb_next(key)
+#define kvpb_find(block, keyid, mode, key) __kvpb_find(keyid, mode, key)
+#define kvpb_get_key(block, keyid, size, buf) __kvpb_get_key(keyid, size, buf)
+#define kvpb_set_key(block, keyid, size, buf) __kvpb_set_key(keyid, size, buf)
+#define kvpb_err_keys(block,keyid) kvpb_set_key(block,keyid,0,NULL) 
+#define kvpb_check(block, mode) __kvpb_check(mode)
+#define kvpb_compact_region(block, mode, keyid) __kvpb_compact_region(mode, keyid)
+#define kvpb_get_cfk(block,mode,size) __kvpb_get_cfk(mode,size)
+#endif
+
+/**
+ * kvpb_for_each - Iterate over all key value pairs
+ * @root: Pointer to the KVPB access information/state structure
+ * @key: Iterator of kvpb_key_t* type
+ * @mode: iteration mode modifier: 0 .. iterate over active/valid data region;
+ *     1 .. iterate over first copy, 2 .. iterate over second copy
+ *
+ * File: keyvalpb.h
+ */
+#define kvpb_for_each(root, key,mode) \
+        for(key=kvpb_first(root,mode);key;\
+            key=kvpb_next(key))
+
+/**
+ * kvpb_for_each - Iterate over all key value pairs matching given key ID
+ * @root: Pointer to the KVPB access information/state structure
+ * @keyid: Ordinal value representing key ID
+ * @key: Iterator of kvpb_key_t* type
+ * @mode: iteration mode modifier: 0 .. iterate over active/valid data region;
+ *     1 .. iterate over first copy, 2 .. iterate over second copy
+ *
+ * File: keyvalpb.h
+ */
+#define kvpb_each_from(root, keyid, mode, key) \
+        for(key=kvpb_find(root,keyid,mode,NULL);key;\
+            key=kvpb_find(root,keyid,mode,key))
+
+#ifdef  KVPB_MINIMALIZED
+#define kvpb_key2data(key) ((void*)(key+1))
+#else  /*KVPB_MINIMALIZED*/
+static inline void* kvpb_key2data(kvpb_key_t *key) { return key+1; }
+#endif  /*KVPB_MINIMALIZED*/
+
+#endif /* _KEYVALPB_H_ */
+
diff --git a/embedded/libs4c/usb/Makefile b/embedded/libs4c/usb/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/libs4c/usb/Makefile.omk b/embedded/libs4c/usb/Makefile.omk
new file mode 100644 (file)
index 0000000..71e412a
--- /dev/null
@@ -0,0 +1,3 @@
+# -*- makefile -*-
+
+SUBDIRS = base pdiusb more lpcusb
diff --git a/embedded/libs4c/usb/base/Makefile b/embedded/libs4c/usb/base/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/libs4c/usb/base/Makefile.omk b/embedded/libs4c/usb/base/Makefile.omk
new file mode 100644 (file)
index 0000000..01d6e0b
--- /dev/null
@@ -0,0 +1,21 @@
+# -*- makefile -*-
+
+default_CONFIG = CONFIG_USB_BASE=n
+
+ifeq ($(CONFIG_USB_BASE),y) 
+lib_LIBRARIES = usbbase
+
+#shared_LIBRARIES = 
+
+#include_HEADERS  = 
+
+nobase_include_HEADERS = usb/usb.h usb/usb_spec.h usb/usb_srq.h usb/usbdebug.h
+
+usbbase_SOURCES = usb.c usbdebug.c 
+
+#lib_LOADLIBES = 
+#bin_PROGRAMS = 
+endif #CONFIG_USB_BASE
+
+
+
diff --git a/embedded/libs4c/usb/base/usb.c b/embedded/libs4c/usb/base/usb.c
new file mode 100644 (file)
index 0000000..2061c8c
--- /dev/null
@@ -0,0 +1,335 @@
+/*****************************************************/
+/***   Module : USB module                         ***/
+/***   Author : Roman Bartosinski (C) 28.04.2002   ***/
+/***   Modify : 08.08.2002, 16.04.2003             ***/
+/*****************************************************/
+
+//#include "hal.h"
+#include <stdio.h>
+#include <string.h>
+#include <system_def.h>
+#include <endian.h>
+#if __BYTE_ORDER == __BIG_ENDIAN
+  #include <byteswap.h>
+#endif
+
+//#include <usb/pdiusb.h> /* to by tu pak nemelo bejt vubec ... */
+#include <usb/usb.h>
+#include <usb/usbdebug.h>
+
+#include <usb/usb_srq.h> /* temporary include - standard control request responses */
+
+/* ep0 buffer */
+  xdata unsigned char ep0_buffer[ MAX_CONTROL_XFER_DATA_SIZE];
+
+  
+/* usb initialize */
+  int usb_init( usb_device_t *udev) {
+    int ret = 0;
+    usb_debug_print( DEBUG_LEVEL_LOW, ("init_usb\r\n"));
+    /* create dynamic fields - endpoints */
+
+    udev->ep_events = 0;
+    udev->flags = 0;
+    udev->configuration = 0;
+    //udev->altinterface = 0;
+    udev->ep0.udev = udev;
+    udev->ep0.flags = USB_STATE_IDLE;
+    udev->ep0.epnum = 0;
+
+//    usb_init_stdreq_fnc( udev);
+
+    if ( usb_udev_is_fnc(udev,init)) {
+      ret = usb_udev_init( udev);
+    }
+    return ret;
+  }
+
+  
+// connecting to USB by SoftConnect
+  int usb_connect( usb_device_t *udev) {
+    int ret = 0;
+    usb_debug_print( DEBUG_LEVEL_LOW,("USB:ON\n"));
+
+    udev->ep_events = 0;
+    udev->flags = 0;
+    udev->configuration = 0;
+    //udev->altinterface = 0;
+    udev->ep0.flags &= ~USB_STATE_MASK; //state = USB_STATE_IDLE;
+
+    if ( usb_udev_is_fnc(udev,connect)) {
+      ret = usb_udev_connect( udev);
+    }
+    return ret;
+  }
+
+  
+  int usb_disconnect( usb_device_t *udev) {
+    int ret = 0;
+    usb_debug_print( DEBUG_LEVEL_LOW,("USB:OFF\n"));
+
+    udev->flags &= ~USB_FLAG_CONFIGURED;
+    udev->configuration = 0;
+    udev->ep_events = 0;
+    //udev->altinterface = 0;
+    udev->ep0.flags &= ~USB_STATE_MASK; //state = USB_STATE_IDLE;
+
+    if ( usb_udev_is_fnc(udev,disconnect)) {
+      ret = usb_udev_disconnect( udev);
+    }
+    return ret;
+  }
+
+  
+  void usb_stall( usb_ep_t *ep) {
+    usb_debug_print( DEBUG_LEVEL_HIGH, ("USB:STALL %1d\n", ep->epnum));
+    if ( usb_udev_is_fnc(ep->udev,stall)) {
+      usb_udev_stall( ep);
+    }
+  }
+
+  
+  int usb_check_events( usb_device_t *udev)
+  {
+    int ret = 0;
+    if ( usb_udev_is_fnc( udev, check_events)) {
+      ret = usb_udev_check_events( udev);
+    }
+    return ret;
+  }
+
+
+// ************************************
+// ***  Control transfer functions  ***
+// ************************************
+
+  void usb_complete_control_transfer(usb_ep_t *ep0, int status) {
+    usb_debug_print( DEBUG_LEVEL_HIGH, ( "CCT:st=%d", status));
+   #ifdef USB_WITH_CB_FNC
+    if ( ep0->complete_fnc )
+      ep0->complete_fnc( ep0, status);
+    ep0->next_pkt_fnc = NULL;
+    ep0->complete_fnc = NULL;
+   #endif /*USB_WITH_CB_FNC*/
+    ep0->flags &= ~USB_STATE_MASK; //state = USB_STATE_IDLE;
+  }
+
+/* Send any data in the data phase of the control transfer */
+  void usb_send_control_data( usb_device_t *udev, unsigned char *pData, unsigned short len) {
+    usb_ep_t *ep0 = &(udev->ep0);
+    usb_debug_print( DEBUG_LEVEL_HIGH, ( "SCD:ptr=%p,s=%d\n", pData, len));
+    ep0->efnc = NULL;
+    ep0->ptr = pData;
+    ep0->actual = 0;
+    if ( ep0->size > len) ep0->size = len;
+    
+    /* Schedule TX processing for later execution */
+    ep0->flags = (ep0->flags & ~USB_STATE_MASK) | USB_STATE_TRANSMIT;
+    udev->flags |= USB_FLAG_EVENT_TX0;
+  }
+
+  void usb_set_control_endfnc( usb_device_t *udev, endfnc_t *efnc) { //REENTRANT_SIGN {
+    udev->ep0.efnc = efnc;
+  }
+
+  void usb_ack_setup( usb_ep_t *ep) {
+    usb_udev_ack_setup(ep->udev);
+  }
+
+  
+/*************************************************************
+ *** Control endpoint0 responses
+ *************************************************************/
+  int usb_control_response( usb_device_t *udev) {
+    int ret = 0;
+    usb_ep_t *ep0 = &(udev->ep0);
+    
+/* response to interrupt BusReset */
+    if ( udev->flags & USB_FLAG_BUS_RESET) {
+      udev->flags &= ~(USB_FLAG_BUS_RESET | USB_FLAG_SUSPEND); // usb_flags.bus_reset = 0; usb_flags.configured = 0;
+      usb_debug_print( DEBUG_LEVEL_MEDIUM, ( "USBreset\n"));
+      ret = 1;
+    }
+/* response to interrupt Suspend */
+    if ( udev->flags & USB_FLAG_SUSPEND) {
+      udev->flags &= ~(USB_FLAG_SUSPEND); //usb_flags.suspend = 0;
+      usb_debug_print( DEBUG_LEVEL_MEDIUM, ( "USBsuspend\n"));
+      ret = 1;
+    }
+
+    
+/* response to interrupt SetupPacket execute response to standard device request or vendor request */
+    if ( udev->flags & USB_FLAG_SETUP) {
+      unsigned char type, req;
+      USB_DEVICE_REQUEST *preq = &(udev->request);
+
+      ep0->ptr = NULL;
+      ep0->size = 0;
+      ep0->actual = 0;
+      ep0->efnc = NULL;
+      ep0->flags &= ~USB_STATE_MASK; //state = USB_STATE_IDLE;
+      udev->flags &= ~USB_FLAG_SETUP;   // usb_flags.setup_packet = 0;
+     #ifdef USB_WITH_CB_FNC
+      ep0->next_pkt_fnc = NULL;
+      ep0->complete_fnc = NULL;
+     #endif /*USB_WITH_CB_FNC*/
+      
+      if ( usb_udev_read_endpoint(ep0, preq, sizeof( USB_DEVICE_REQUEST)) 
+                                   != sizeof( USB_DEVICE_REQUEST)) {
+        usb_udev_stall( ep0);
+        return -1;
+      }
+     #if __BYTE_ORDER == __BIG_ENDIAN
+      preq->wValue  = bswap_16( preq->wValue);
+      preq->wIndex  = bswap_16( preq->wIndex);
+      preq->wLength = bswap_16( preq->wLength);
+     #endif
+      usb_debug_print( DEBUG_LEVEL_MEDIUM,( "SePa:x%02X,x%02X,x%04X,x%04X,x%04X\n", preq->bmRequestType, preq->bRequest, preq->wValue, preq->wIndex, preq->wLength));
+      
+      // acknowledge setup here
+      if(usb_udev_is_fnc( udev, ack_control_setup)) {
+        usb_udev_ack_control_setup(udev);
+      }
+      
+      ep0->size = preq->wLength;
+      if ((( preq->bmRequestType & USB_DATA_DIR_MASK) == USB_DATA_DIR_FROM_HOST) && preq->wLength) {
+        ep0->ptr = ep0_buffer;
+        ep0->flags = (ep0->flags & ~USB_STATE_MASK) | USB_STATE_RECEIVE;
+      }
+      
+      type = preq->bmRequestType & USB_REQUEST_TYPE_MASK;
+      req = preq->bRequest & USB_REQUEST_MASK;
+      if ( type == USB_STANDARD_REQUEST) {
+        int ret = -1;
+        usb_debug_print( DEBUG_LEVEL_HIGH, ( "StdReq-%d\n", req));
+/*        
+        if ( (udev->stdreq[ req]) != NULL) {
+          ret = udev->stdreq[ req]( udev);
+        }
+        if( ret < 0)
+          udev->ack_setup( udev);
+*/          
+        switch( req) {
+          case USB_REQUEST_GET_STATUS:        ret=usb_stdreq_get_status( udev); break;
+          case USB_REQUEST_CLEAR_FEATURE:     ret=usb_stdreq_clear_feature( udev); break;
+          case USB_REQUEST_SET_FEATURE:       ret=usb_stdreq_set_feature( udev); break;
+          case USB_REQUEST_SET_ADDRESS:       ret=usb_stdreq_set_address( udev); break;
+
+          case USB_REQUEST_GET_DESCRIPTOR:    ret=usb_stdreq_get_descriptor( udev); break;
+//          case USB_REQUEST_SET_DESCRIPTOR:    break;
+          case USB_REQUEST_GET_CONFIGURATION: ret=usb_stdreq_get_configuration( udev); break;
+          case USB_REQUEST_SET_CONFIGURATION: ret=usb_stdreq_set_configuration( udev); break;
+          case USB_REQUEST_GET_INTERFACE:     ret=usb_stdreq_get_interface( udev); break;
+          case USB_REQUEST_SET_INTERFACE:     ret=usb_stdreq_set_interface( udev); break;
+//          case USB_REQUEST_SYNC_FRAME:        break;
+//          default:                            ret=-1; break;
+        }
+        if (ret<0)
+          usb_udev_stall( ep0);
+      } else {
+        if ( type == USB_VENDOR_REQUEST) {
+//putchar('#');
+         #ifdef USB_WITH_CB_FNC
+          int ret = -1;
+//         if(USBVendorRequestCBFnc != NULL)
+//         ret = USBVendorRequestCBFnc(&usb_ep0, &dreq);
+          if ( udev->vendor_fnc != NULL)
+            ret = udev->vendor_fnc( udev);
+          if ( ret < 0)
+            usb_udev_stall( ep0);
+//         #else /*USB_WITH_CB_FNC*/
+//          if ( USBVendorRequest(&dreq) == -1)
+//          udev->ack_setup( udev);
+         #endif /*USB_WITH_CB_FNC*/
+        } else if ( type == USB_CLASS_REQUEST) {
+         #ifdef USB_WITH_CB_FNC
+          int ret = -1;
+//         if(USBClassRequestCBFnc != NULL)
+//         ret = USBClassRequestCBFnc(&usb_ep0, &dreq);
+          if( udev->class_fnc != NULL)
+            ret = udev->class_fnc( udev);
+          if( ret < 0)
+            usb_udev_stall( ep0);
+//         #else /*USB_WITH_CB_FNC*/
+//          if ( USBClassRequest(&dreq) == -1)
+//          udev->ack_setup( udev);
+         #endif /*USB_WITH_CB_FNC*/
+        } else
+            usb_udev_stall( ep0);
+      }
+      ret = 1;
+    }
+    
+/* response to interrupt Ep0RxInt  - receive data */
+    if ( udev->flags & USB_FLAG_EVENT_RX0) {
+      int i;
+      udev->flags &= ~USB_FLAG_EVENT_RX0;
+      usb_debug_print( DEBUG_LEVEL_MEDIUM, ( "Ep0Rx\n"));
+      if (( ep0->flags & USB_STATE_MASK) == USB_STATE_RECEIVE) {
+        usb_debug_print( DEBUG_LEVEL_HIGH, ( "RCV:p=%04lX,s=%d\n", (unsigned long)ep0->ptr, ep0->size));
+
+        i = usb_udev_read_endpoint(ep0, ep0->ptr, ep0->max_packet_size);
+        ep0->actual += i;
+        ep0->ptr +=i;
+
+       #ifdef USB_WITH_CB_FNC
+       if ( ep0->next_pkt_fnc ) {
+          if( ep0->next_pkt_fnc( ep0, i, USB_NEXT_PKT_REC) < 0) {
+            usb_udev_stall( ep0);
+            return -1;
+          }
+        }
+       #endif /*USB_WITH_CB_FNC*/
+
+        if (( i != ep0->max_packet_size) || ( ep0->actual >= ep0->size)) {
+          usb_complete_control_transfer( ep0, USB_COMPLETE_OK );
+          if ( ep0->efnc) {
+            ep0->efnc(ep0);
+          }
+        }
+      } else {
+        ep0->flags &= ~USB_STATE_MASK; //state = USB_STATE_IDLE;
+      }
+    }
+
+/* response to interrupt Ep0TxInt */
+    if ( udev->flags & USB_FLAG_EVENT_TX0) { 
+      short i = ep0->size - ep0->actual;
+      udev->flags &= ~USB_FLAG_EVENT_TX0;
+//usb_debug_print( DEBUG_LEVEL_LOW, ("0S-%d(%d){%d}\n", ep0->state, ep0->size, ep0->max_packet_size));
+      usb_debug_print( DEBUG_LEVEL_MEDIUM, ( "EP0Tx:i=%d\n", i));
+
+      if (( ep0->flags & USB_STATE_MASK) == USB_STATE_TRANSMIT) {
+      
+        if(i > ep0->max_packet_size) i = ep0->max_packet_size;
+
+        if ( i > 0 ) {
+         #ifdef USB_WITH_CB_FNC
+          if ( ep0->next_pkt_fnc) {
+            if( ep0->next_pkt_fnc( ep0, i, USB_NEXT_PKT_SEND) < 0) {
+              usb_udev_stall( ep0);
+              return -1;
+            }
+          }
+         #endif /*USB_WITH_CB_FNC*/
+    usb_debug_print( DEBUG_LEVEL_HIGH, ("Wr(%d)\n",i));
+          usb_udev_write_endpoint( ep0, ep0->ptr, i);
+          ep0->actual += i;
+          ep0->ptr +=i;
+
+          if( i != ep0->max_packet_size) {
+            /* last packed without full size has been sent, state can change to idle */
+            usb_complete_control_transfer( ep0, USB_COMPLETE_OK );
+          }
+        } else {
+           usb_udev_ack_setup( udev);   // Send zero packet at the end ???
+          usb_complete_control_transfer( ep0, USB_COMPLETE_OK );
+        }
+      }
+      ret = 1;
+    }
+
+    return ret;
+  }
+
+
diff --git a/embedded/libs4c/usb/base/usb/usb.h b/embedded/libs4c/usb/base/usb/usb.h
new file mode 100644 (file)
index 0000000..40338a6
--- /dev/null
@@ -0,0 +1,181 @@
+/**************************************************************/
+/***   Module : USB module - header file                    ***/
+/***   Author : Roman Bartosinski (C) 28.04.2002            ***/
+/***   Modify : 08.08.2002                                  ***/
+/***   Rewrite: 05.09.2002                                  ***/
+/**************************************************************/
+
+#ifndef _USB_MODULE_
+  #define _USB_MODULE_
+
+  #include "usb_spec.h"
+  
+#if defined(SDCC) || defined(__KEIL__) || defined(__C51__)
+  /*8051 special handling*/
+  #define REENTRANT_SIGN reentrant
+#else
+  #define xdata           /*nothing*/
+  #define REENTRANT_SIGN  /*nothing*/
+#endif
+
+#define USB_WITH_CB_FNC
+//#define USB_WITH_UDEV_FNC
+
+#ifdef USB_WITH_UDEV_FNC
+  #define USB_UDEV_REENTRANT_SIGN REENTRANT_SIGN
+#else /*USB_WITH_UDEV_FNC*/
+  #define USB_UDEV_REENTRANT_SIGN /*nothing*/
+#endif /*USB_WITH_UDEV_FNC*/
+
+/* control endpoint */
+  #define MAX_CONTROL_XFER_DATA_SIZE 8
+
+  struct usb_ep_t;
+  
+  typedef void endfnc_t( struct  usb_ep_t *ep) REENTRANT_SIGN;
+  
+  #define USB_NEXT_PKT_SEND 0
+  #define USB_NEXT_PKT_REC  1
+
+  #define USB_COMPLETE_OK   0
+  #define USB_COMPLETE_FAIL -1
+
+  typedef struct usb_ep_t {
+    struct usb_device_t *udev;      /* pointer to parent device */
+    unsigned short max_packet_size; /* max. size of endpoint package, e.g. PDI_EP0_PACKET_SIZE */
+    unsigned char *ptr;             /* pointer to current transmitted data */
+    unsigned int  size;             /* full size of current transmitted data */
+    unsigned int  actual;           /* transmitted data size */
+    endfnc_t *efnc;                 /* ??? */
+    unsigned char flags;            /* endpoint flags & state - idle,receiving, transmitting  ??? HERE ??? */
+    unsigned char epnum;            /* endpoint number (index) - endpoint0 must be set to 0 */
+    unsigned short event_mask;      /* event(interrupt) mask for this endpoint, e.g. PDI_INT_EP1_IN for pdiusbd1x */
+   #ifdef USB_WITH_CB_FNC
+    int (*next_pkt_fnc)(struct usb_ep_t *ep, int len, int codeval) REENTRANT_SIGN;
+    int (*complete_fnc)(struct usb_ep_t *ep, int status) REENTRANT_SIGN;
+    long user_data;
+   #endif /*USB_WITH_CB_FNC*/
+  } usb_ep_t;
+
+
+/* Vendor & Class functions */
+/*
+ #ifdef USB_WITH_CB_FNC
+  typedef int usb_vendor_extension_fnc_t(usb_ep_t *ep, USB_DEVICE_REQUEST *dreq);
+  extern xdata usb_vendor_extension_fnc_t USBVendorRequestCBFnc;
+
+  typedef int usb_class_extension_fnc_t(usb_ep_t *ep, USB_DEVICE_REQUEST *dreq);
+  extern xdata usb_class_extension_fnc_t USBClassRequestCBFnc;
+ #else //USB_WITH_CB_FNC
+  char USBVendorRequest( USB_DEVICE_REQUEST *dr);
+  char USBClassRequest( USB_DEVICE_REQUEST *dr);
+ #endif //USB_WITH_CB_FNC
+*/
+
+/* USB device */  
+  typedef struct usb_device_t {
+    unsigned char id;               /* device ID ??? */
+    unsigned char flags;            /* usb device flags + endpoint0 events */
+    unsigned char ep_events;        /* one bit for each endpoint (without ep0) event,(bit0 for udev->ep[0], bit1 for udev->ep[1], ...)*/
+    unsigned char configuration;    /* current configuration */
+//    unsigned char interface;        /* current interface */
+//    unsigned char altinterface;     /* current alternative interface */
+
+    //int (stdreq[13])( struct usb_device_t *udev) REENTRANT_SIGN;    /* pointer to array of standard request processing functions */
+    int (*vendor_fnc)( struct usb_device_t *udev) REENTRANT_SIGN;     /* pointer to vendor request processing function */
+    int (*class_fnc)( struct usb_device_t *udev) REENTRANT_SIGN;      /* pointer to class request processing function */
+
+   #ifdef USB_WITH_UDEV_FNC
+    int (*init)( struct usb_device_t *udev) REENTRANT_SIGN;              /* function for hw specific part of initialize usb device */
+    int (*connect)( struct usb_device_t *udev) REENTRANT_SIGN;           /* function for hw specific part of connecting device to usb */
+    int (*disconnect)( struct usb_device_t *udev) REENTRANT_SIGN;        /* function for hw specific part of disconnecting device to usb */
+    void (*ack_setup)( struct usb_device_t *udev) REENTRANT_SIGN;        /* function for hw specific part of control response acknowledge */
+    void (*ack_control_setup)( struct usb_device_t *udev) REENTRANT_SIGN;        /* function for hw specific part of control response acknowledge */
+    int (*check_events)( struct usb_device_t *udev) REENTRANT_SIGN;      /* hw specific part of function for checking events */
+    void (*stall)( usb_ep_t *ep) REENTRANT_SIGN;                         /* hw specific function for stall endpoint */
+    int (*read_endpoint)( usb_ep_t *ep, void *ptr, int size) REENTRANT_SIGN;
+    int (*write_endpoint)( usb_ep_t *ep, const void *ptr, int size) REENTRANT_SIGN;
+   #endif /*USB_WITH_UDEV_FNC*/
+    
+//    USB_DEVICE_REQUEST *request;   /* current usb request - only if there is a valid usb request in processing */
+    USB_DEVICE_REQUEST request;    /* usb device request */
+    
+    unsigned char cntep;           /* number of device endpoints in ep array without EP0 */
+    usb_ep_t ep0;                  /* endpoint 0 */
+    usb_ep_t *ep;                 /* others endpoints in array */
+  } usb_device_t;
+
+
+/* endpoint flags */
+  /* endpoint state */
+  #define USB_STATE_IDLE       0x00
+  #define USB_STATE_TRANSMIT   0x01
+  #define USB_STATE_RECEIVE    0x02
+  #define USB_STATE_MASK       0x03
+
+/* usb_device flags */
+  #define USB_FLAG_CONFIGURED   0x01
+  #define USB_FLAG_BUS_RESET    0x02
+  #define USB_FLAG_SUSPEND      0x04
+  #define USB_FLAG_SETUP        0x08 // setup_packet
+  #define USB_FLAG_REMOTE_WAKE  0x10
+  
+  #define USB_FLAG_EVENT_RX0  0x40
+  #define USB_FLAG_EVENT_TX0  0x80
+  
+
+
+/* device functions - inline ??? */
+  int usb_init( usb_device_t *udev);
+  int usb_connect( usb_device_t *udev);
+  int usb_disconnect( usb_device_t *udev);
+  void usb_stall( usb_ep_t *ep);
+  
+  #define usb_stall_ep0( udev) \
+    do { \
+      usb_stall( &(udev->ep0)); \
+    } while(0)
+
+/* check usb events(interrupts) */
+  int usb_check_events( usb_device_t *udev);
+/* response to standard constrol requests */
+  int usb_control_response( usb_device_t *udev);  
+/* send control data */
+  void usb_send_control_data( usb_device_t *udev, unsigned char *pData, unsigned short len);
+  void usb_set_control_endfnc( usb_device_t *udev, endfnc_t *efnc);// REENTRANT_SIGN;
+  void usb_ack_setup( usb_ep_t *ep);
+
+  
+/* Standard requests functions */
+//  typedef int (*usb_stdreq_fnc_t)( usb_device_t *udev) REENTRANT_SIGN;
+//  extern xdata usb_stdreq_fnc_t usb_standard_requests[13];
+  
+
+#ifdef USB_WITH_UDEV_FNC
+
+  #define usb_udev_is_fnc(_M_udev, _M_fnc) (_M_udev->_M_fnc)
+  
+  #define usb_udev_init(_M_udev) (_M_udev->init(_M_udev))
+  #define usb_udev_connect(_M_udev) (_M_udev->connect(_M_udev))
+  #define usb_udev_disconnect(_M_udev) (_M_udev->disconnect(_M_udev))
+  #define usb_udev_ack_setup(_M_udev) (_M_udev->ack_setup(_M_udev))
+  #define usb_udev_ack_control_setup(_M_udev) (_M_udev->ack_control_setup(_M_udev))
+  #define usb_udev_check_events(_M_udev) (_M_udev->check_events(_M_udev))
+
+  #define usb_udev_stall(_M_ep) ((_M_ep)->udev->stall(_M_ep))
+
+  #define usb_udev_read_endpoint(_M_ep, _M_ptr, _M_size) \
+       ((_M_ep)->udev->read_endpoint(_M_ep, _M_ptr, _M_size))
+
+  #define usb_udev_write_endpoint(_M_ep, _M_ptr, _M_size) \
+       ((_M_ep)->udev->write_endpoint(_M_ep, _M_ptr, _M_size))
+
+#else /*USB_WITH_UDEV_FNC*/
+
+  #define USB_PDI_DIRECT_FNC
+  #include "pdi.h"
+
+#endif /*USB_WITH_UDEV_FNC*/
+#endif
diff --git a/embedded/libs4c/usb/base/usb/usb_spec.h b/embedded/libs4c/usb/base/usb/usb_spec.h
new file mode 100644 (file)
index 0000000..841a2a4
--- /dev/null
@@ -0,0 +1,228 @@
+/*************************************************/
+/***   Module : USB specification              ***/
+/***   Author : Roman Bartosinski 29.07.2002   ***/
+/***   Modify : 08.08.2002, 14.01.2003         ***/
+/*************************************************/
+
+#ifndef _USB_SPECIFICATIONS_AND_DEFINITIONS_MODULE
+ #define _USB_SPECIFICATIONS_AND_DEFINITIONS_MODULE
+
+/*#include <inttypes.h>*/
+#include <types.h>
+
+#ifndef PACKED
+  #ifdef  __GNUC__
+    #define PACKED __attribute__((packed))
+  #else /*__GNUC__*/
+    #define PACKED /*nothing*/
+  #endif /*__GNUC__*/
+#endif
+
+/* this section is from __USB100.H__ and __CHAP9.H__ and define USB constants and structs */
+
+/* *** USB Device Request *** (spec. 9.3) */
+  typedef struct _tag_usb_device_request {
+    uint8_t  bmRequestType;
+    uint8_t  bRequest;
+    uint16_t wValue;
+    uint16_t wIndex;
+    uint16_t wLength;
+  } USB_DEVICE_REQUEST;
+
+/****************************************************************************************/
+/*** definitions for USB tranfer standard packets described in USB secif. - chapter 9 ***/
+/****************************************************************************************/
+  #define DEVICE_ADDRESS_MASK   0x7F
+
+/* bmRequestType D7 - Data transfer direction */
+  #define USB_DATA_DIR_MASK        (uint8_t)0x80
+  #define USB_DATA_DIR_FROM_HOST   (uint8_t)0x00
+  #define USB_DATA_DIR_TO_HOST     (uint8_t)0x80
+/* bmRequestType D4..D0 - Recipient */
+  #define USB_RECIPIENT            (uint8_t)0x1F
+  #define USB_RECIPIENT_DEVICE     (uint8_t)0x00
+  #define USB_RECIPIENT_INTERFACE  (uint8_t)0x01
+  #define USB_RECIPIENT_ENDPOINT   (uint8_t)0x02
+  #define USB_RECIPIENT_OTHER      (uint8_t)0x03
+/* bmRequestType D6..D5 - Type */
+  #define USB_REQUEST_TYPE_MASK    (uint8_t)0x60
+  #define USB_STANDARD_REQUEST     (uint8_t)0x00
+  #define USB_CLASS_REQUEST        (uint8_t)0x20
+  #define USB_VENDOR_REQUEST       (uint8_t)0x40
+/* Standard request codes (spec. 9.4) */
+  #define USB_REQUEST_MASK         (uint8_t)0x0F
+  #define USB_REQUEST_GET_STATUS                  0x00
+  #define USB_REQUEST_CLEAR_FEATURE               0x01
+  #define USB_REQUEST_SET_FEATURE                 0x03
+  #define USB_REQUEST_SET_ADDRESS                 0x05
+  #define USB_REQUEST_GET_DESCRIPTOR              0x06
+  #define USB_REQUEST_SET_DESCRIPTOR              0x07
+  #define USB_REQUEST_GET_CONFIGURATION           0x08
+  #define USB_REQUEST_SET_CONFIGURATION           0x09
+  #define USB_REQUEST_GET_INTERFACE               0x0A
+  #define USB_REQUEST_SET_INTERFACE               0x0B
+  #define USB_REQUEST_SYNC_FRAME                  0x0C
+/* Descriptor types (spec. 9.4) */
+  #define USB_DESCRIPTOR_TYPE_DEVICE                    0x01
+  #define USB_DESCRIPTOR_TYPE_CONFIGURATION             0x02
+  #define USB_DESCRIPTOR_TYPE_STRING                    0x03
+  #define USB_DESCRIPTOR_TYPE_INTERFACE                 0x04
+  #define USB_DESCRIPTOR_TYPE_ENDPOINT                  0x05
+  #define USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER          0x06
+  #define USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION 0x07
+  #define USB_DESCRIPTOR_TYPE_POWER                     0x08
+
+/* values for the bits returned by the USB GET_STATUS command (spec. 9.4.5) */
+  #define USB_GETSTATUS_SELF_POWERED                0x01
+  #define USB_GETSTATUS_REMOTE_WAKEUP_ENABLED       0x02
+
+/* values for standard request Clear Feature */
+  #define USB_FEATURE_ENDPOINT_STALL          0x0000
+  #define USB_FEATURE_REMOTE_WAKEUP           0x0001
+
+
+/*******************************************************/
+/*** Standard USB Descriptor Definitions (spec. 9.6) ***/
+/*******************************************************/
+
+/* *** DEVICE *** (spec. 9.6.1) */
+  struct _tag_usb_device_descriptor {
+    uint8_t  bLength;
+    uint8_t  bDescriptorType;
+    uint16_t bcdUSB;
+    uint8_t  bDeviceClass;
+    uint8_t  bDeviceSubClass;
+    uint8_t  bDeviceProtocol;
+    uint8_t  bMaxPacketSize0;
+    uint16_t idVendor;
+    uint16_t idProduct;
+    uint16_t bcdDevice;
+    uint8_t  iManufacturer;
+    uint8_t  iProduct;
+    uint8_t  iSerialNumber;
+    uint8_t  bNumConfigurations;
+  } PACKED;
+  typedef struct _tag_usb_device_descriptor
+    USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR;
+
+/* *** DEVICE_QUALIFIER *** (spec. 9.6.2) */
+  struct _tag_usb_device_qualifier_descriptor {
+    uint8_t  bLength;
+    uint8_t  bDescriptorType;
+    uint16_t bcdUSB;
+    uint8_t  bDeviceClass;
+    uint8_t  bDeviceSubClass;
+    uint8_t  bDeviceProtocol;
+    uint8_t  bMaxPacketSize0;
+    uint8_t  bNumConfigurations;
+    uint8_t  bReserved;
+  } PACKED;
+  typedef struct _tag_usb_device_qualifier_descriptor
+    USB_DEVICE_QUALIFIER_DESCRIPTOR, *PUSB_DEVICE_QUALIFIER_DESCRIPTOR;
+
+/* *** CONFIGURATION *** (spec. 9.6.3) */
+  struct _tag_usb_configuration_descriptor {
+    uint8_t  bLength;
+    uint8_t  bDescriptorType;
+    uint16_t wTotalLength;
+    uint8_t  bNumInterfaces;
+    uint8_t  bConfigurationValue;
+    uint8_t  iConfiguration;
+    uint8_t  bmAttributes;
+    uint8_t  MaxPower;
+  } PACKED;
+  typedef struct _tag_usb_configuration_descriptor
+    USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR;
+/* definitions for bits in the bmAttributes field of a configuration descriptor. (spec. 9.6.3) */
+  #define USB_CONFIG_POWERED_MASK  0xc0
+  #define USB_CONFIG_BUS_POWERED   0x80
+  #define USB_CONFIG_SELF_POWERED  0x40
+  #define USB_CONFIG_REMOTE_WAKEUP 0x20
+  #define BUS_POWERED              0x80
+  #define SELF_POWERED             0x40
+  #define REMOTE_WAKEUP            0x20
+
+/* *** OTHER_SPEED_CONFIGURATION *** (spec. 9.6.4) */
+  struct _tag_usb_other_speed_configuration {
+    uint8_t  bLength;
+    uint8_t  bDescriptorType;
+    uint16_t wTotalLength;
+    uint8_t  bNumInterfaces;
+    uint8_t  bConfigurationValue;
+    uint8_t  iConfiguration;
+    uint8_t  bmAttributes;
+    uint8_t  bMaxPower;
+  } PACKED;
+  typedef struct _tag_usb_other_speed_configuration
+    USB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR, *PUSB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR;
+
+/* *** INTERFACE *** (spec. 9.6.5) */
+  struct _tag_usb_interface_descriptor {
+    uint8_t  bLength;
+    uint8_t  bDescriptorType;
+    uint8_t  bInterfaceNumber;
+    uint8_t  bAlternateSetting;
+    uint8_t  bNumEndpoints;
+    uint8_t  bInterfaceClass;
+    uint8_t  bInterfaceSubClass;
+    uint8_t  bInterfaceProtocol;
+    uint8_t  iInterface;
+  } PACKED;
+  typedef struct _tag_usb_interface_descriptor
+    USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR;
+
+/* *** ENDPOINT *** (spec. 9.6.6) */
+  struct _tag_usb_endpoint_descriptor {
+    uint8_t  bLength;
+    uint8_t  bDescriptorType;
+    uint8_t  bEndpointAddress;
+    uint8_t  bmAttributes;
+    uint16_t wMaxPacketSize;
+    uint8_t  bInterval;
+  } PACKED;
+  typedef struct _tag_usb_endpoint_descriptor
+    USB_ENDPOINT_DESCRIPTOR, *PUSB_ENDPOINT_DESCRIPTOR;
+
+/* Endpoint direction bit, stored in address (spec. 9.6.6) */
+  #define USB_ENDPOINT_DIRECTION_MASK               0x80
+/* test direction bit in the bEndpointAddress field of an endpoint descriptor. */
+  #define USB_ENDPOINT_DIRECTION_OUT(addr)          (!((addr) & USB_ENDPOINT_DIRECTION_MASK))
+  #define USB_ENDPOINT_DIRECTION_IN(addr)           ((addr) & USB_ENDPOINT_DIRECTION_MASK)
+/* Values for bmAttributes field of an endpoint descriptor (spec. 9.6.6) */
+  #define USB_ENDPOINT_TYPE_MASK                    0x03
+  #define USB_ENDPOINT_TYPE_CONTROL                 0x00
+  #define USB_ENDPOINT_TYPE_ISOCHRONOUS             0x01
+  #define USB_ENDPOINT_TYPE_BULK                    0x02
+  #define USB_ENDPOINT_TYPE_INTERRUPT               0x03
+
+/* *** STRING *** (spec. 9.6.7) */
+  struct _tag_usb_string_descriptor {
+    uint8_t  bLength;
+    uint8_t  bDescriptorType;
+    uint8_t  *bString;
+  } PACKED;
+  typedef struct _tag_usb_string_descriptor
+    USB_STRING_DESCRIPTOR, *PUSB_STRING_DESCRIPTOR;
+
+
+/*******************************************/
+/*** USB_IF - Defined USB device classes ***/
+/*******************************************/
+  #define USB_DEVICE_CLASS_RESERVED             0x00
+  #define USB_DEVICE_CLASS_AUDIO                0x01
+  #define USB_DEVICE_CLASS_COMMUNICATIONS       0x02
+  #define USB_DEVICE_CLASS_HUMAN_INTERFACE      0x03
+  #define USB_DEVICE_CLASS_MONITOR              0x04
+  #define USB_DEVICE_CLASS_PHYSICAL_INTERFACE   0x05
+  #define USB_DEVICE_CLASS_POWER                0x06
+  #define USB_DEVICE_CLASS_PRINTER              0x07
+  #define USB_DEVICE_CLASS_STORAGE              0x08
+  #define USB_DEVICE_CLASS_HUB                  0x09
+  #define USB_DEVICE_CLASS_APPLICATION_SPECIFIC 0xFE
+  #define USB_DEVICE_CLASS_VENDOR_SPECIFIC      0xFF
+
+  /* define application specific device class subclasses */
+  #define USB_APPL_SUBCLASS_FIRMWARE_UPDATE     0x01
+  #define USB_APPL_SUBCLASS_IRDA_USB_BRIDGE     0x02
+
+#endif
diff --git a/embedded/libs4c/usb/base/usb/usb_srq.h b/embedded/libs4c/usb/base/usb/usb_srq.h
new file mode 100644 (file)
index 0000000..1821ab4
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef _USB_STDREQ_MODULE_
+  #define _USB_STDREQ_MODULE_
+
+  int usb_stdreq_get_status( usb_device_t *udev);
+  
+  int usb_stdreq_clear_feature( usb_device_t *udev);
+
+  int usb_stdreq_set_feature( usb_device_t *udev);
+
+  int usb_stdreq_set_address( usb_device_t *udev);
+
+  int usb_stdreq_get_configuration( usb_device_t *udev);
+
+  int usb_stdreq_set_configuration( usb_device_t *udev);
+
+  int usb_stdreq_get_interface( usb_device_t *udev);
+
+  int usb_stdreq_set_interface( usb_device_t *udev);
+  int usb_stdreq_get_descriptor( usb_device_t *udev);
+  
+#endif /*_USB_STDREQ_MODULE_*/
+
diff --git a/embedded/libs4c/usb/base/usb/usbdebug.h b/embedded/libs4c/usb/base/usb/usbdebug.h
new file mode 100644 (file)
index 0000000..6a82e83
--- /dev/null
@@ -0,0 +1,81 @@
+/* Global debug macros, variables, functions - header file */
+/* R.B. - 23.4.2003 */
+
+#ifndef _USB_DEBUG_H_
+#define _USB_DEBUG_H_
+
+#if 1
+  #include <stdio.h>
+  #define usb_printf printf
+#else
+  int simple_printf(const char *f, ...);
+  #define usb_printf simple_printf
+#endif
+
+/* Debug levels */
+#define DEBUG_LEVEL_NONE    0
+#define DEBUG_LEVEL_LOW     1
+#define DEBUG_LEVEL_MEDIUM  2
+#define DEBUG_LEVEL_HIGH    3
+#define DEBUG_LEVEL_VERBOSE 4
+
+#ifndef DEBUG_STATIC_LEVEL
+/* Global static debug level */
+#define DEBUG_STATIC_LEVEL     DEBUG_LEVEL_NONE
+#endif
+
+/* If it is defined, current global debug level is
+   in 'global_debug_level' variable. Otherwise will
+   be used 'DEBUG_STATIC_LEVEL' as current global
+   debug level
+*/
+/*#define DEBUG_USE_DYNAMIC_LEVEL*/
+
+/* #define DEBUG */
+
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+
+#ifdef DEBUG
+
+/* use static or dynamic global debug level */
+#if defined(DEBUG_USE_DYNAMIC_LEVEL) /* use dynamic debug level */
+  extern unsigned char usb_debug_level;
+#else /* use only static debug level */
+  #define usb_debug_level DEBUG_STATIC_LEVEL
+#endif
+
+
+/* usb_debug_print( level, printargs) print debug info in printargs if
+   level is lower or equal to 'global_debug_level'/'DEBUG_STATIC_LEVEL'.
+   'printargs' is with parenthesis.
+   usage : usb_debug_print( DEBUG_LEVEL_MEDIUM,("i=%d",i));
+*/
+#define usb_debug_print( _lvl_, _prnargs_)      \
+  do {                                          \
+    if ( usb_debug_level >= _lvl_) {            \
+      usb_printf _prnargs_;                     \
+    }                                           \
+  } while(0)
+
+/* usb_debug_info( printargs) print debug info always
+   usage : usb_debug_info( "debug info");
+*/
+#define usb_debug_info usb_printf  /* FIXME: this is not correct */
+
+#else /* DEBUG */
+  #define usb_debug_print( _lvl_, _prnargs_)
+  #define usb_debug_info(...) 
+#endif /* DEBUG */
+
+
+  void usb_debug_set_level(int level);
+
+  char *usb_debug_get_req_recipient( char rqt);
+  char *usb_debug_get_req_type( char rqt);
+  char *usb_debug_get_std_request( char req);
+  char *usb_debug_get_std_descriptor( unsigned char desc);
+
+  
+#endif /* _GLOBAL_DEBUG_H_ */
diff --git a/embedded/libs4c/usb/base/usbdebug.c b/embedded/libs4c/usb/base/usbdebug.c
new file mode 100644 (file)
index 0000000..48bee80
--- /dev/null
@@ -0,0 +1,76 @@
+/* Global debug macros, variables, functions - header file */
+/* R.B. - 23.4.2003 */
+
+#include <usb/usbdebug.h>
+#include <usb/usb_spec.h>
+
+#ifdef DEBUG
+
+/* debug can be enabled in run-time */
+#if defined(DEBUG_USE_DYNAMIC_LEVEL) /* use dynamic debug level */
+  unsigned char usb_debug_level = DEBUG_LEVEL_NONE;
+#endif  
+
+/*************************************************************
+ *** Debug infos
+ *************************************************************/
+
+  void usb_debug_set_level(int level) {
+   #if defined(DEBUG_USE_DYNAMIC_LEVEL) /* use dynamic debug level */
+    usb_debug_level = level;
+   #endif  
+  }
+
+  
+  char *usb_debug_get_req_recipient( char rqt) {
+    switch ( rqt & USB_RECIPIENT) {
+      case USB_RECIPIENT_DEVICE:    return "DEVICE";
+      case USB_RECIPIENT_INTERFACE: return "INTERFACE";
+      case USB_RECIPIENT_ENDPOINT:  return "ENDPOINT";
+    }
+    return "OTHER";
+  }
+  char *usb_debug_get_req_type( char rqt) {
+    switch ( rqt & USB_REQUEST_TYPE_MASK) {
+      case USB_STANDARD_REQUEST: return "STANDARD";
+      case USB_CLASS_REQUEST:    return "CLASS";
+      case USB_VENDOR_REQUEST:   return "VENDOR";
+    }
+    return "RESERVED";
+  }
+  char *usb_debug_get_std_request( char req) {
+    switch ( req & USB_REQUEST_MASK) {
+      case USB_REQUEST_GET_STATUS:        return "GET STATUS";
+      case USB_REQUEST_CLEAR_FEATURE:     return "CLEAR FEATURE";
+      case USB_REQUEST_SET_FEATURE:       return "SET FEATURE";
+      case USB_REQUEST_SET_ADDRESS:       return "SET ADDRESS";
+
+      case USB_REQUEST_GET_DESCRIPTOR:    return "GET DESCRIPTOR";
+      case USB_REQUEST_SET_DESCRIPTOR:    return "SET DESCRIPTOR";
+      case USB_REQUEST_GET_CONFIGURATION: return "GET CONFIGURATION";
+      case USB_REQUEST_SET_CONFIGURATION: return "SET CONFIGURATION";
+      case USB_REQUEST_GET_INTERFACE:     return "GET INTERFACE";
+      case USB_REQUEST_SET_INTERFACE:     return "SET INTERFACE";
+      case USB_REQUEST_SYNC_FRAME:        return "SYNC FRAME";
+    }
+    return "UNKNOWN";
+  }
+  char *usb_debug_get_std_descriptor( unsigned char desc) {
+
+    switch ( desc) {
+      case USB_DESCRIPTOR_TYPE_DEVICE:                    return "DEVICE";
+      case USB_DESCRIPTOR_TYPE_CONFIGURATION:             return "CONFIGURATION";
+      case USB_DESCRIPTOR_TYPE_STRING:                    return "STRING";
+      case USB_DESCRIPTOR_TYPE_INTERFACE:                 return "INTERFACE";
+      case USB_DESCRIPTOR_TYPE_ENDPOINT:                  return "ENDPOINT";
+      case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER:          return "DEVICE_QUALIFIER";
+      case USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION: return "OTHER_SPEED_CONFIG";
+      case USB_DESCRIPTOR_TYPE_POWER:                     return "POWER";
+    }
+    return "UNKNOWN";
+  }
+
+#else /*DEBUG*/  
+  void usb_debug_set_level(int level) {
+  }
+#endif /* DEBUG */
diff --git a/embedded/libs4c/usb/lpcusb/Makefile b/embedded/libs4c/usb/lpcusb/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/libs4c/usb/lpcusb/Makefile.omk b/embedded/libs4c/usb/lpcusb/Makefile.omk
new file mode 100644 (file)
index 0000000..00a4c72
--- /dev/null
@@ -0,0 +1,11 @@
+# -*- makefile -*-
+
+default_CONFIG = CONFIG_USB_LPCUSB=n
+
+ifeq ($(CONFIG_USB_LPCUSB),y) 
+lib_LIBRARIES = lpcusb
+
+nobase_include_HEADERS = usb/lpcusb.h usb/lpc.h
+
+lpcusb_SOURCES = lpcusb.c lpc.c
+endif #CONFIG_USB_LPCUSB
diff --git a/embedded/libs4c/usb/lpcusb/lpc.c b/embedded/libs4c/usb/lpcusb/lpc.c
new file mode 100644 (file)
index 0000000..7d9f20c
--- /dev/null
@@ -0,0 +1,162 @@
+/*****************************************************/
+/***   Module : USB PDI                            ***/
+/***   Author : Roman Bartosinski (C) 28.04.2002   ***/
+/***   Modify : 08.08.2002, 16.04.2003             ***/
+/*****************************************************/
+
+#include <system_def.h>
+#include <usb/usb.h>
+#include <usb/lpcusb.h>
+
+/* connect usb */
+int usb_lpc_connect( usb_device_t *udev) {
+  lpc_write_cmd_data(USB_CMD_SET_DEV_STAT,USB_DAT_WR_BYTE(USBC_DEV_CON));
+  return 0;
+}
+
+/* disconnect usb */
+int usb_lpc_disconnect( usb_device_t *udev) {
+  lpc_write_cmd_data(USB_CMD_SET_DEV_STAT,USB_DAT_WR_BYTE(0));
+  return 0;
+}
+
+/* acknowledge control transfer */
+void usb_lpc_ack_setup( usb_device_t *udev) {
+  lpc_usb_write_endpoint(0x80|0x00, NULL, 0);
+}
+
+/* stall endpoint X */
+void usb_lpc_stall( usb_ep_t *ep) {
+  if ( ep->epnum) {
+    lpc_write_cmd_data(USB_CMD_SEL_EP_CLRI(lpc_ep2addr(ep->epnum)),USB_DAT_WR_BYTE(USBC_EP_STAT_ST));
+  } else { // endpoint0
+    lpc_write_cmd_data(USB_CMD_SEL_EP_CLRI(lpc_ep2addr(0x80|ep->epnum)),USB_DAT_WR_BYTE(USBC_EP_STAT_ST));
+    lpc_write_cmd_data(USB_CMD_SEL_EP_CLRI(lpc_ep2addr(ep->epnum)),USB_DAT_WR_BYTE(USBC_EP_STAT_ST));
+  }
+}
+
+/**
+ * usb_lpc_check events
+ * function reads interrupt register and sets event flags
+ * function returns 1 if there is some new event.
+ * function returns 0 if there isn't new event but all is OK
+ * function returns -1 if there is any error
+*/
+int usb_lpc_check_events( usb_device_t *udev) 
+{
+  unsigned int disr,val,last_int;
+  int ret=0,n,m,i;
+
+  disr=USBDevIntSt;
+
+  /* Device Status Interrupt (Reset, Connect change, Suspend/Resume) */
+  if (disr & USBDevInt_DEV_STAT) {
+    USBDevIntClr = USBDevInt_DEV_STAT;
+    disr&=~USBDevInt_DEV_STAT;
+    lpc_write_cmd(USB_CMD_GET_DEV_STAT);
+    val=lpc_read_cmd_data(USB_DAT_GET_DEV_STAT);
+    if (val & USBC_DEV_RST) {               /* Reset */
+      lpc_usb_reset();
+      udev->flags |= USB_FLAG_BUS_RESET;
+      ret = 1;
+    }
+    if (val & USBC_DEV_SUS_CH) {            /* Suspend/Resume */
+      if (val & USBC_DEV_SUS) {             /* Suspend */
+        udev->flags |= USB_FLAG_SUSPEND;
+        ret = 1;
+      } else {                              /* Resume */
+        /* todo */
+      }
+    }
+  }
+
+  /* Endpoint's Slow Interrupt */
+  if (disr & USBDevInt_EP_SLOW) {
+    USBDevIntClr = USBDevInt_EP_SLOW;
+    disr&=~USBDevInt_EP_SLOW;
+
+    last_int = USBEpIntSt;
+
+    /* EP0_OUT */
+    if (last_int & (1 << 0)) {
+      last_int &= ~(1 << 0);
+      USBEpIntClr = 1 << 0;
+      lpc_wait4devint(USBDevInt_CDFULL);
+      val = USBCmdData;
+      /* Setup Packet */
+      if (val & USBC_EP_SEL_STP)   
+        udev->flags |= USB_FLAG_SETUP;
+      else
+        udev->flags |= USB_FLAG_EVENT_RX0;
+      ret = 1;
+    }
+
+    /* EP0_IN */
+    if (last_int & (1 << 1)) {
+      last_int &= ~(1 << 1);
+      USBEpIntClr = 1 << 1;
+      lpc_wait4devint(USBDevInt_CDFULL);
+      val = USBCmdData;
+      udev->flags |= USB_FLAG_EVENT_TX0;
+      ret = 1;
+    }    
+
+    /* user endpoints */
+    for( i=0; i<udev->cntep; i++) {
+      if ( last_int & (udev->ep+i)->event_mask) {
+        last_int &= ~((udev->ep+i)->event_mask);
+        USBEpIntClr = (udev->ep+i)->event_mask;
+        lpc_wait4devint(USBDevInt_CDFULL);
+        val = USBCmdData;
+        udev->ep_events |= 1<<i;
+        ret = 1;
+      }
+    }
+
+    while (last_int) {                    /* Endpoint Interrupt Status */
+      for (n = 0; n < USB_EP_NUM; n++) {    /* Check All Endpoints */
+        if (last_int & (1 << n)) {
+          last_int &= ~(1 << n);
+          USBEpIntClr = 1 << n;
+          m = n >> 1;
+          if (n&1) m|=0x80;
+          lpc_wait4devint(USBDevInt_CDFULL);
+          val = USBCmdData;
+          lpc_usb_setstallEP(m);
+        }
+      }
+    }
+  }
+  if (!disr)
+    USBDevIntClr = disr;
+  return ret;
+}
+
+int usb_lpc_read_endpoint( usb_ep_t *ep, void *ptr, int size)
+{
+  return lpc_usb_read_endpoint(ep->epnum, ptr, size);
+}
+
+int usb_lpc_write_endpoint( usb_ep_t *ep, const void *ptr, int size)
+{
+  return lpc_usb_write_endpoint(0x80|ep->epnum, ptr, size);
+}
+
+
+/* init usb structures and chip */
+int usb_lpc_init( usb_device_t *udev) {
+
+  udev->connect = usb_lpc_connect;
+  udev->disconnect = usb_lpc_disconnect;
+  udev->ack_setup = usb_lpc_ack_setup; 
+  udev->ack_control_setup = NULL;
+  udev->stall = usb_lpc_stall;
+  udev->check_events = usb_lpc_check_events;
+  udev->read_endpoint = usb_lpc_read_endpoint;
+  udev->write_endpoint = usb_lpc_write_endpoint;
+
+  udev->ep0.max_packet_size = USB_MAX_PACKET0;
+
+  lpc_usb_hw_init();  
+  return 0;
+}
diff --git a/embedded/libs4c/usb/lpcusb/lpcusb.c b/embedded/libs4c/usb/lpcusb/lpcusb.c
new file mode 100644 (file)
index 0000000..1cf130d
--- /dev/null
@@ -0,0 +1,195 @@
+/*****************************************************/
+/***   Module : USB PDI                            ***/
+/***   Author : Roman Bartosinski (C) 28.04.2002   ***/
+/***   Modify : 08.08.2002, 16.04.2003             ***/
+/*****************************************************/
+
+#include <system_def.h>
+#include <usb/usb.h>
+#include <usb/lpcusb.h>
+
+unsigned int lpc_ep2addr(unsigned int ep_num) 
+{
+  unsigned int val;
+  val = (ep_num & 0x0F) << 1;
+  if (ep_num & 0x80) 
+    val += 1;
+  return val;
+} 
+
+void lpc_wait4devint(unsigned int intrs) 
+{
+  while ((USBDevIntSt & intrs) != intrs);
+  USBDevIntClr = intrs;  
+}
+
+
+void lpc_write_cmd(unsigned int cmd) 
+{
+  USBDevIntClr = USBDevInt_CCEMTY | USBDevInt_CDFULL;
+  USBCmdCode = cmd;
+  lpc_wait4devint(USBDevInt_CCEMTY);
+}
+
+void lpc_write_cmd_data (unsigned int cmd, unsigned int val) 
+{
+  lpc_write_cmd(cmd);
+  USBCmdCode = val;
+  lpc_wait4devint(USBDevInt_CCEMTY);
+}
+
+unsigned int lpc_read_cmd_data (unsigned int cmd)
+{
+  lpc_write_cmd(cmd);
+  lpc_wait4devint(USBDevInt_CDFULL);
+  return USBCmdData;
+} 
+
+void lpc_usb_realizeEP(unsigned int idx,unsigned int wmaxpsize)
+{
+  USBReEp |= (1 << idx);
+  USBEpInd = idx;
+  USBMaxPSize = wmaxpsize;
+  lpc_wait4devint(USBDevInt_EP_RLZED);
+}
+
+void lpc_usb_configEP(unsigned int ep_num,unsigned int wmaxpsize)
+{
+  lpc_usb_realizeEP(lpc_ep2addr(ep_num),wmaxpsize);
+  lpc_usb_enableEP(ep_num);
+}
+
+void lpc_usb_setstallEP(unsigned int ep_num) 
+{
+  lpc_write_cmd_data(USB_CMD_SET_EP_STAT(lpc_ep2addr(ep_num)),USB_DAT_WR_BYTE(USBC_EP_STAT_ST));
+}
+
+void lpc_usb_clrstallEP(unsigned int ep_num) 
+{
+  lpc_write_cmd_data(USB_CMD_SET_EP_STAT(lpc_ep2addr(ep_num)),USB_DAT_WR_BYTE(0));
+}
+
+void lpc_usb_enableEP(unsigned int ep_num) 
+{
+  lpc_write_cmd_data(USB_CMD_SET_EP_STAT(lpc_ep2addr(ep_num)),USB_DAT_WR_BYTE(0));
+}
+
+void lpc_usb_disableEP(unsigned int ep_num) 
+{
+  lpc_write_cmd_data(USB_CMD_SET_EP_STAT(lpc_ep2addr(ep_num)),USB_DAT_WR_BYTE(USBC_EP_STAT_DA));
+}
+
+void lpc_usb_set_addr(unsigned int adr)
+{
+  lpc_write_cmd_data(USB_CMD_SET_ADDR,USB_DAT_WR_BYTE(USBC_DEV_EN | adr)); /*  Setup Status Phase */
+}
+
+void lpc_usb_config_device(int fConfigured)
+{
+  lpc_write_cmd_data(USB_CMD_CFG_DEV,USB_DAT_WR_BYTE(fConfigured ? USBC_CONF_DEVICE : 0)); /*  Setup Status Phase */
+}
+
+void lpc_usb_reset(void)
+{
+  USBEpIntClr  = 0xFFFFFFFF;
+  USBEpIntEn   = 0xFFFFFFFF ^ USB_DMA_EP;
+  USBDevIntClr = 0xFFFFFFFF;
+  USBDevIntEn  = USBDevInt_DEV_STAT | USBDevInt_EP_SLOW;
+
+  lpc_usb_configEP(0x00, USB_MAX_PACKET0);
+  lpc_usb_configEP(0x80, USB_MAX_PACKET0);
+}
+
+void lpc_usb_hw_init (void) 
+{
+
+  PINSEL1 &= ~0xC000C000;
+//  PINSEL1 |=  0x40004000;                   /* Select USB Link, VBUS */
+  PINSEL1 |=  0x80000000;                   /* Select USB Link, VBUS */
+
+  PCONP |= 0x80000000;                      /* Turn On USB PCLK */
+
+  /* Configure 48MHz USB Clock;  FOsc = 12MHz, M = 4, P = 2 */
+  PLLCFG48  = 0x23;                         /* M = 4, P = 2 */
+  PLLCON48  = PLLCON_PLLE;                  /* PLL Enable */
+  PLLFEED48 = 0xAA;                         /* Feed Sequence 1 */
+  PLLFEED48 = 0x55;                         /* Feed Sequence 2 */
+
+  while ((PLLSTAT48 & PLLSTAT_LOCK) == 0);  /* Wait for PLL Lock */
+
+  PLLCON48  = PLLCON_PLLE | PLLCON_PLLC;    /* PLL Enable & Connect */
+  PLLFEED48 = 0xAA;                         /* Feed Sequence 1 */
+  PLLFEED48 = 0x55;                         /* Feed Sequence 2 */
+
+  USBDevIntEn  = USBDevInt_DEV_STAT;        /* Enable Device Status Interrupt */
+
+  /* Partial Manual Reset since Automatic Bus Reset is not working */
+  lpc_usb_reset();
+  lpc_usb_set_addr(0);
+}
+
+/*
+ * lpc_usb_read_endpoint: Read USB Endpoint Data
+ * @EPNum: Endpoint Number - EPNum.0..3: Address, EPNum.7: Dir
+ * @ptr: Pointer to Data Buffer
+ * @size:
+ * Return Value: Number of bytes read
+ */
+int lpc_usb_read_endpoint( unsigned int ep_num, void *ptr, int size)
+{
+  unsigned int cnt,i,dwData;
+  unsigned char *p=ptr;
+
+  USBCtrl = ((ep_num & 0x0F) << 2) | USBCtrl_RD_EN;
+  do {
+    cnt = USBRxPLen;
+  } while ((cnt & USBRxPLen_PKT_RDY) == 0);
+  cnt &= USBRxPLen_PKT_LNGTH;
+
+  // get data
+  while (USBCtrl & USBCtrl_RD_EN) {
+    dwData = USBRxData;
+    if (p != NULL) {
+      for (i = 0; i < 4; i++) {
+       if (size-- != 0) {
+         *p = dwData & 0xFF;
+          p++;
+       }
+       dwData >>= 8;
+      }
+    }
+  }
+
+  lpc_write_cmd(USB_CMD_SEL_EP(lpc_ep2addr(ep_num)));
+  lpc_write_cmd(USB_CMD_CLR_BUF);
+
+  return cnt;
+}
+
+/*
+ * lpc_usb_write_endpoint: Write USB Endpoint Data
+ * @ep_num: Endpoint Number - ep_num.0..3: Address, ep_num.7: Dir
+ * @ptr: Pointer to Data Buffer
+ * @size:   Number of bytes to write
+ * Return Value:    Number of bytes written
+ */
+int lpc_usb_write_endpoint( unsigned int ep_num, const void *ptr, int size)
+{
+  unsigned int n;
+  const unsigned char *p=ptr;
+
+  USBCtrl = ((ep_num & 0x0F) << 2) | USBCtrl_WR_EN;
+  USBTxPLen = size;
+
+  for (n = 0; n < (size + 3) / 4; n++) {
+    USBTxData = (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0];
+    p += 4;
+  }
+
+  USBCtrl=0;
+
+  lpc_write_cmd(USB_CMD_SEL_EP(lpc_ep2addr(ep_num)));
+  lpc_write_cmd(USB_CMD_VALID_BUF);
+
+  return size;
+}
diff --git a/embedded/libs4c/usb/lpcusb/usb/lpc.h b/embedded/libs4c/usb/lpcusb/usb/lpc.h
new file mode 100644 (file)
index 0000000..c693182
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _USB_LPC_SUBMODULE_HEADER_FILE_
+#define _USB_LPC_SUBMODULE_HEADER_FILE_
+
+#include <usb/usb.h>
+int usb_lpc_init( usb_device_t *udev);
+
+#endif /* _USB_LPC_SUBMODULE_HEADER_FILE_ */
+
diff --git a/embedded/libs4c/usb/lpcusb/usb/lpcusb.h b/embedded/libs4c/usb/lpcusb/usb/lpcusb.h
new file mode 100644 (file)
index 0000000..0f111bb
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef _LPCUSB_BASE_MODULE
+#define _PLCUSB_BASE_MODULE
+
+/*********************************************************/
+// Function prototypes
+//
+// LPCUSB common commands
+unsigned int lpc_ep2addr(unsigned int ep_num);
+void lpc_wait4devint(unsigned int intrs);
+void lpc_write_cmd(unsigned int cmd);
+void lpc_write_cmd_data (unsigned int cmd, unsigned int val);
+unsigned int lpc_read_cmd_data (unsigned int cmd);
+void lpc_usb_realizeEP(unsigned int idx,unsigned int wmaxpsize);
+void lpc_usb_configEP(unsigned int ep_num,unsigned int wmaxpsize);
+void lpc_usb_setstallEP (unsigned int ep_num);
+void lpc_usb_clrstallEP (unsigned int ep_num);
+void lpc_usb_enableEP(unsigned int ep_num); 
+void lpc_usb_disableEP(unsigned int ep_num);
+void lpc_usb_config_device(int fConfigured);
+void lpc_usb_reset(void);
+void lpc_usb_set_addr(unsigned int adr);
+void lpc_usb_hw_init (void);
+int lpc_usb_read_endpoint( unsigned int ep_num, void *ptr, int size);
+int lpc_usb_write_endpoint( unsigned int ep_num, const void *ptr, int size);
+
+#endif // from _LPC_BASE_MODULE
diff --git a/embedded/libs4c/usb/more/Makefile b/embedded/libs4c/usb/more/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/libs4c/usb/more/Makefile.omk b/embedded/libs4c/usb/more/Makefile.omk
new file mode 100644 (file)
index 0000000..c28fbda
--- /dev/null
@@ -0,0 +1,18 @@
+# -*- makefile -*-
+
+default_CONFIG = CONFIG_USB_MORE=n
+
+ifeq ($(CONFIG_USB_MORE),y) 
+lib_LIBRARIES = usbmore
+
+#shared_LIBRARIES = 
+
+#include_HEADERS  = 
+
+usbmore_SOURCES = usb_srq.c
+
+#lib_LOADLIBES = 
+#bin_PROGRAMS = 
+
+endif #CONFIG_USB_MORE
+
diff --git a/embedded/libs4c/usb/more/usb/msc_loader.h b/embedded/libs4c/usb/more/usb/msc_loader.h
new file mode 100644 (file)
index 0000000..f912d2b
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _MSC_LOADER_H
+#define _MSC_LOADER_H
+
+#include <usb/usb_loader.h>
+
+int usb_msc1210_loader(usb_device_t *udev);
+
+#endif /*_MSC_LOADER_H*/
diff --git a/embedded/libs4c/usb/more/usb/usb_com.h b/embedded/libs4c/usb/more/usb/usb_com.h
new file mode 100644 (file)
index 0000000..1f87b9b
--- /dev/null
@@ -0,0 +1,17 @@
+
+#ifndef _USB_COM_H
+  #define _USB_COM_H
+  
+/* Queued USB Module */
+  extern int usb_tm_snd;
+  extern int usb_tm_snded;
+  extern int usb_tm_rcv;
+  
+  int usb_com_init( void);
+  void usb_com_start_send( void);
+  
+  int usb_com_sendch(int c);
+  int usb_com_recch();
+  int usb_com_sendstr(const char *s);
+
+#endif /* _USB_COM_H */
diff --git a/embedded/libs4c/usb/more/usb/usb_loader.h b/embedded/libs4c/usb/more/usb/usb_loader.h
new file mode 100644 (file)
index 0000000..5c215e4
--- /dev/null
@@ -0,0 +1,31 @@
+#include <usb/usb.h>
+
+#ifndef _USB_LOADER_H
+#define _USB_LOADER_H
+
+#define USB_VENDOR_GET_CAPABILITIES  0x00 // get capabilities
+#define USB_VENDOR_RESET_DEVICE      0x08
+// #define USB_VENDOR_SET_BYTE          0x10
+// #define USB_VENDOR_SET_WORD          0x20
+#define USB_VENDOR_GET_SET_MEMORY    0x30
+#define USB_VENDOR_ERASE_MEMORY      0x40 // erase memory for 1 Byte
+#define USB_VENDOR_ERASE_1KB_MEMORY  0x48 // erase memory for 1 KB
+#define USB_VENDOR_MASS_ERASE        0x50 // erase all device memory
+#define USB_VENDOR_GOTO              0x60
+#define USB_VENDOR_CALL              0x70
+#define USB_VENDOR_GET_STATUS        0xF0
+#define USB_VENDOR_MASK              0xF8 // mask for vendor commands
+
+#define USB_VENDOR_MEMORY_BY_BULK    0x80
+
+#if 0 /* MSP430 */
+#define USB_VENDOR_TARGET_ADAPTER    0x01
+#define USB_VENDOR_TARGET_MSP430     0x02
+#else /* MSC1210 */
+#define USB_VENDOR_TARGET_DATA       0x01
+#define USB_VENDOR_TARGET_XDATA      0x02
+#endif
+
+#define USB_VENDOR_TARGET_MASK       0x07
+
+#endif /*_USB_LOADER_H*/
diff --git a/embedded/libs4c/usb/more/usb_com.c b/embedded/libs4c/usb/more/usb_com.c
new file mode 100644 (file)
index 0000000..71991ba
--- /dev/null
@@ -0,0 +1,1061 @@
+/*********************************************************/
+/***   Module : USB communication                      ***/
+/***   Author : Roman Bartosinski (bartosr@centrum.cz) ***/
+/***   Modify : 14.01.2003                             ***/
+/*********************************************************/
+
+#include <cpu_def.h>
+#include <system_def.h>
+#include <stdio.h>
+#include "pdiusb.h"
+#include <h8s2633h.h>
+/*#include <usb/usb_spec.h>*/
+#include "usb_defs.h"
+#include <usb/usb.h>
+#include <usb/usb_com.h>
+
+
+/* Queued USB Module */
+typedef volatile struct{
+  unsigned char *first;
+  unsigned char *last;
+  unsigned char *begin;
+  unsigned char *end;
+} usb_com_que_t;
+
+#define USB_COM_BUF_LEN    80 //(80*8)
+
+usb_com_que_t usb_com_que_in;  /* input queue */
+unsigned char usb_com_buf_in[USB_COM_BUF_LEN];
+usb_com_que_t usb_com_que_out; /* output queue */
+unsigned char usb_com_buf_out[USB_COM_BUF_LEN];
+
+int usb_com_init( void);
+int usb_com_put(usb_com_que_t *q, int c);
+int usb_com_get(usb_com_que_t *q);
+
+usb_vendor_extension_fnc_t *usb_vendor_extension=0;
+
+#ifdef PDIUSB_WITH_ADD_IRQ_HANDLER
+/* usb irq handler struct */
+irq_handler_t usb_irq_handler;
+#elif defined(PDIUSB_WITH_EXCPTVECT_SET)
+void usb_isr(void) __attribute__ ((interrupt_handler));
+#endif /*PDIUSB_WITH_EXCPTVECT_SET*/
+
+int usb_irq_cnt;
+
+/* common external function for pdiusb module */
+  void pdiSendCommand( unsigned char byCmd) {
+    writeb( byCmd, PDIUSB_COMMAND_ADDR);
+  }
+  unsigned char pdiReadData( unsigned char byCount, unsigned char *pbyData) {
+    unsigned char out = byCount;
+    
+    while (byCount--) {
+      *pbyData = readb( PDIUSB_READ_DATA_ADDR);
+      pbyData++;
+    }
+    
+    return out;
+  }
+  void pdiWriteData( unsigned char byCount, unsigned char *pbyData) {
+    while (byCount--) {
+      writeb( *pbyData++, PDIUSB_WRITE_DATA_ADDR);
+    }
+  }            
+  
+  
+/* usb communication module */
+  /* data */
+  usb_flags_t usb_flags;  
+  unsigned char usb_address;
+  unsigned char usb_interface;
+  usb_control_ep_t usb_rxtx_control;
+  usb_bulk_ep_t usb_rx_bulk, usb_tx_bulk;
+  
+  volatile unsigned int usb_last_irq;
+  // internal buffer for data from/to control req. - must be global
+  unsigned char ctrl_data[PDI_EP0_PACKET_SIZE];
+                   
+  typeof(msec_time) usb_start = 0, usb_stop = 0;
+  
+
+    
+/* functions */
+  int usb_run( void) {
+    int ret = 0;
+    if ( usb_flags.running) {
+#ifdef USE_USB_WITH_IRQ
+      if (!usb_flags.bits.was_int) return ret;
+      usb_flags.was_int = 0;
+#else
+      ret = usb_test_interrupt();
+      if ( usb_flags.request == 1) {
+        usb_answer_to_request();
+      }
+      if ( usb_flags.request == 2) { // request is set in  usb_answer_to_request()
+        if (( usb_rxtx_control.dreq.bmRequestType & USB_DATA_DIR_MASK)==USB_DATA_DIR_TO_HOST) {
+          unsigned int now = usb_rxtx_control.bytes;
+          if ( now > PDI_EP0_PACKET_SIZE) now = PDI_EP0_PACKET_SIZE;
+         if ( usb_rxtx_control.next_pkt_fnc )
+           if( usb_rxtx_control.next_pkt_fnc(&usb_rxtx_control, now, USB_NEXT_PKT_SEND) ) {
+              usb_stall_ep0();
+             return -1;
+           }
+          debugPrint( DBG_HIGH, ("CNTR send 1.data (%d)\n", now));
+          pdiWriteEndpoint( PDI_EP0_TX, now, usb_rxtx_control.data);
+          usb_rxtx_control.data += now;
+          if ( !(usb_rxtx_control.bytes -= now)) {
+            usb_flags.request = 3;
+          }
+        }
+      }
+      if ( usb_flags.request == 3) {
+        if ( !usb_rxtx_control.dreq.wLength ||
+             (usb_rxtx_control.dreq.bmRequestType & USB_DATA_DIR_MASK)==USB_DATA_DIR_FROM_HOST) {
+          pdiWriteEndpoint( PDI_EP0_TX, 0, 0);
+         if ( usb_rxtx_control.complete_fnc )
+           usb_rxtx_control.complete_fnc(&usb_rxtx_control, USB_COMPLETE_OK);
+         usb_rxtx_control.next_pkt_fnc = NULL;
+         usb_rxtx_control.complete_fnc = NULL;
+        }
+      }
+#endif
+    }
+    return ret;
+  }  
+  
+  int usb_test_interrupt( void) { //_naked {
+    unsigned char usb_last_status;
+    int ret = 0;
+//    INTERRUPT_PRE(0);
+//    LEDr = 1;
+//    EA=0;
+    usb_last_irq = pdiGetInterrupt();
+    if ( usb_last_irq) {
+      ret = 1;
+      debugPrint( DBG_MEDIUM, ("USB Interrupt 0x%X\n",usb_last_irq));
+      if ( usb_last_irq & PDI_INT_BUSRESET) {                  // D12 - Bus reset reached
+        usb_flags.configured = 0;
+        if ( usb_flags.running && usb_flags.stop_request) {
+          usb_flags.running = 0;
+          usb_flags.stop_request = 0;
+        }
+        debugPrint( DBG_HIGH, ("Bus Reset\n"));
+      } else {
+        if ( usb_last_irq & PDI_INT_SUSPEND) {            // D12 - Suspend flag changed
+          debugPrint( DBG_HIGH, ("Suspend Changed\n"));
+        }
+        // it must be first b/c tx and rx can be sended all together
+        if ( usb_last_irq & PDI_INT_EP0_IN) {                 // D12 - Ep0TxDone - data in EP0 was sended
+          usb_last_status = pdiGetLastTransStatus( PDI_EP0_TX);
+          debugPrint( DBG_HIGH, ("Ep0-Tx LTS=0x%X\n", usb_last_status));    
+          if (( usb_last_status & PDI_LTSTAT_RXTX_OK) && usb_flags.request > 1) {
+            if ( usb_flags.request == 2) {
+              unsigned int now = usb_rxtx_control.bytes;
+              if ( now > PDI_EP0_PACKET_SIZE) now = PDI_EP0_PACKET_SIZE;
+
+             if ( usb_rxtx_control.next_pkt_fnc )
+               if( usb_rxtx_control.next_pkt_fnc(&usb_rxtx_control, now, USB_NEXT_PKT_SEND) ) {
+                 usb_stall_ep0();
+                 return -1;
+               }
+
+              debugPrint( DBG_HIGH, ("CNTR data\n"));
+              pdiWriteEndpoint( PDI_EP0_TX, now, usb_rxtx_control.data);
+              usb_rxtx_control.data += now;
+              if ( !(usb_rxtx_control.bytes -= now)) {
+                usb_flags.request = 3;
+              }
+            } else if ( usb_flags.request == 3) {
+              debugPrint( DBG_HIGH, ("CNTR ack\n"));
+              usb_flags.request = 0;
+             
+             if ( usb_rxtx_control.complete_fnc )
+               usb_rxtx_control.complete_fnc(&usb_rxtx_control, USB_COMPLETE_OK);
+             usb_rxtx_control.next_pkt_fnc = NULL;
+             usb_rxtx_control.complete_fnc = NULL;
+             
+            } else {
+              debugPrint( DBG_LOW, ("tx ... ???\n"));
+            }
+          }
+        }
+        
+        if ( usb_last_irq & PDI_INT_EP0_OUT) {                // D12 - Ep0RxDone - some data was received in EP0
+          usb_last_status = pdiGetLastTransStatus( PDI_EP0_RX);
+          debugPrint( DBG_HIGH, ("Ep0-Rx LTS=0x%X\n", usb_last_status));
+          if ( usb_last_status & PDI_LTSTAT_RXTX_OK) {
+            if ( usb_last_status & PDI_LTSTAT_SETUP) {
+              if ( usb_flags.request) {
+                debugPrint( DBG_HIGH, ("!!! New setup, but last not ack ...\n"));
+              }
+              usb_flags.request = 1; // Standard_requests();
+             if ( usb_rxtx_control.complete_fnc )
+               usb_rxtx_control.complete_fnc(&usb_rxtx_control, USB_COMPLETE_FAIL);
+             usb_rxtx_control.next_pkt_fnc = NULL;
+             usb_rxtx_control.complete_fnc = NULL;
+            } else {
+              if ( usb_flags.request == 2) {
+                unsigned int now = usb_rxtx_control.bytes;
+                if ( now > PDI_EP0_PACKET_SIZE) now = PDI_EP0_PACKET_SIZE;
+                debugPrint( DBG_HIGH, ("CNTR data\n"));
+                ret = pdiReadEndpoint( PDI_EP0_RX, now, usb_rxtx_control.data);
+               
+               if(ret>usb_rxtx_control.bytes)
+                 ret = usb_rxtx_control.bytes;
+               
+               usb_rxtx_control.data += ret;
+               
+               if ( usb_rxtx_control.next_pkt_fnc ) {
+                 if( usb_rxtx_control.next_pkt_fnc(&usb_rxtx_control, ret, USB_NEXT_PKT_REC) ) {
+                    usb_stall_ep0();
+                   return -1;
+                 }
+               }
+               
+                if (!(usb_rxtx_control.bytes -= ret)) {
+                  usb_rxtx_control.data -= usb_rxtx_control.dreq.wLength;
+                  usb_flags.request = 3;
+                }
+              } else if ( usb_flags.request == 3) {
+                debugPrint( DBG_HIGH, ("CNTR ack\n"));
+                usb_flags.request = 0;
+                pdiReadEndpoint( PDI_EP0_RX, 0, 0);
+               if ( usb_rxtx_control.complete_fnc )
+                 usb_rxtx_control.complete_fnc(&usb_rxtx_control, USB_COMPLETE_OK);
+               usb_rxtx_control.next_pkt_fnc = NULL;
+               usb_rxtx_control.complete_fnc = NULL;
+              } else {
+                pdiReadEndpoint( PDI_EP0_RX, 0, 0);
+              }
+            }
+          }
+        }
+        if ( usb_last_irq & PDI_INT_EP1_OUT) {                // D12 - Ep1RxDone - some data was received in EP1
+          usb_last_status = pdiGetLastTransStatus( PDI_EP1_RX);
+          debugPrint( DBG_HIGH, ("Ep1-Rx LTS=0x%X\n", usb_last_status));
+          if ( usb_last_status & PDI_LTSTAT_RXTX_OK) {
+            pdiSetEpStatus( PDI_EP1_OUT, PDI_SET_EP_STALLED);
+          }
+        }
+        if ( usb_last_irq & PDI_INT_EP1_IN) {                 // D12 - Ep1TxDone - data in EP1 was sended
+          usb_last_status = pdiGetLastTransStatus( PDI_EP1_TX);
+          debugPrint( DBG_HIGH, ("Ep1-Tx LTS=0x%X\n", usb_last_status));
+          if ( usb_last_status & PDI_LTSTAT_RXTX_OK) {
+            pdiSetEpStatus( PDI_EP1_IN, PDI_SET_EP_STALLED);
+          }
+        }
+
+        if ( usb_last_irq & PDI_INT_EP2_OUT) {                // D12 - Ep2RxDone - some data was received in EP2
+          usb_last_status = pdiGetLastTransStatus( PDI_EP2_RX);
+          debugPrint( DBG_HIGH, ("Ep2-Rx LTS=0x%X\n", usb_last_status));
+          if ( usb_last_status & PDI_LTSTAT_RXTX_OK) {            
+            if ( usb_flags.terminal_mode) {
+              unsigned char hlpbfr[PDI_EP2_PACKET_SIZE], now = PDI_EP2_PACKET_SIZE, i;
+            MoreRead:
+              now = pdiReadEndpoint( PDI_EP2_RX, now, hlpbfr);
+              for(i=0;i<now;i++) {
+                usb_tm_rcv++;
+                if (usb_com_put( &usb_com_que_in, hlpbfr[i])<0) { /* nevkladat dalsi */
+                  break;
+                }
+              }
+              if(now==PDI_EP2_PACKET_SIZE) goto MoreRead;              
+            } else {
+              unsigned long now = usb_rx_bulk.remain;
+              if ( now > PDI_EP2_PACKET_SIZE) now = PDI_EP2_PACKET_SIZE;
+  
+              if ( !usb_flags.bits.bulk_rx_data) {
+                usb_flags.bulk_rx_data = 1;
+                usb_start = msec_time;
+              }
+  
+              ReadAgain:
+                ret = pdiReadEndpoint( PDI_EP2_RX, now, usb_rx_bulk.data);
+                usb_rx_bulk.data += now;
+                if ( !( usb_rx_bulk.remain -= now)) {
+                  //usb_rx_bulk.data -= usb_rx_bulk.bytes; /* read again */
+                  usb_stop = msec_time;              
+                  usb_flags.bulk_rx_data = 0;
+                // complete_func or set flag(event)
+                }
+              if ( usb_rx_bulk.remain > 0 && usb_rx_bulk.remain <= PDI_EP2_PACKET_SIZE) 
+                goto ReadAgain;
+            }
+          }
+        }
+        if ( usb_last_irq & PDI_INT_EP2_IN) {                 // D12 - Ep2TxDone - data in EP2 was sended
+          usb_last_status = pdiGetLastTransStatus( PDI_EP2_TX);
+          debugPrint( DBG_HIGH, ("Ep2-Tx LTS=0x%X\n", usb_last_status));
+          if ( usb_last_status & PDI_LTSTAT_RXTX_OK) {
+            if ( usb_flags.terminal_mode) {
+              int ch = usb_com_get( &usb_com_que_out);
+              usb_tm_snded++;
+              if ( ch < 0) {
+                usb_flags.bulk_tx_data = 0;                
+              } else {
+                unsigned char uchr = ch;
+                usb_flags.bulk_tx_data = 1;
+                pdiWriteEndpoint( PDI_EP2_TX, 1, &uchr);
+              }
+            } else {
+              if ( usb_tx_bulk.remain) {
+                unsigned int now = usb_tx_bulk.remain;
+                if ( now > PDI_EP2_PACKET_SIZE) now = PDI_EP2_PACKET_SIZE;
+                pdiWriteEndpoint( PDI_EP2_TX, now, usb_tx_bulk.data);
+                usb_tx_bulk.data += now;
+                if (!(usb_tx_bulk.remain -= now)) {
+                  // complete_func or set flag(event)
+                }
+              }
+            }
+          }
+        }
+        ret = 0;
+      }
+    }
+//    EA=1;
+//    LEDr = 0;
+//    INTERRUPT_POST();
+   return ret;
+  }
+
+
+// ************************************
+  void usb_init( void) {
+    usb_last_irq = 0; usb_address = 0; usb_interface = 0;
+    usb_flags.word = 0;
+    
+    usb_com_init();
+
+#ifdef USE_USB_WITH_IRQ
+    usb_irq_cnt=0;
+   #ifdef PDIUSB_WITH_ADD_IRQ_HANDLER
+    if( test_irq_handler( ISR_USB_INTV, &usb_irq_handler)==0)
+      add_irq_handler( ISR_USB_INTV, &usb_irq_handler);
+   #elif defined(PDIUSB_WITH_EXCPTVECT_SET)
+    excptvec_set(ISR_USB_INTV,&usb_isr);
+   #endif /*PDIUSB_WITH_ADD_IRQ_HANDLER*/
+    //*((char*)0xfffa1f) |= 0x04; /* It must be here for pull-up INT signal in usb_isr function */
+#endif    
+    debugPrint(DBG_MEDIUM,("# Usb Inited\n"));    
+  }
+
+  void usb_connect_bus( void) {
+    debugPrint(DBG_MEDIUM,("Usb connect to bus\n"));
+    usb_flags.running = 1;
+    usb_last_irq = 0;
+    pdiSetDMA( PDI_DMA_EP4_INT | PDI_DMA_EP5_INT); // ???
+    pdiSetMode( PDI_MODE_NO_LAZY_CLOCK | PDI_MODE_CLOCK_RUNNING | PDI_MODE_SOFT_CONNECT | PDI_CLOCK_SET_TO_ONE | PDI_CLOCK_4M);
+  }
+  void usb_disconnect_bus( void) {
+    debugPrint(DBG_MEDIUM,("Usb disconnect from bus\n"));
+    pdiSetMode( PDI_MODE_NO_LAZY_CLOCK | PDI_MODE_CLOCK_RUNNING | PDI_CLOCK_SET_TO_ONE | PDI_CLOCK_4M);
+    usb_flags.configured = 0;
+    usb_flags.stop_request = 1;
+  }
+
+  void usb_stall_ep0( void) {
+    pdiSetEpStatus( PDI_EP0_TX, PDI_SET_EP_STALLED); pdiSetEpStatus( PDI_EP0_RX, PDI_SET_EP_STALLED);
+  }
+  
+
+// ************************************
+// ***   Common send/receive fncs   ***
+// ************************************
+/*
+  void usb_send_to_usb( unsigned char idx, unsigned char maxb) {
+    debugPrint( DBG_HIGH,("USB Send EP#%d (max=%d) <- buff 0x%lX, cnt %d\n",usb_ep[idx].ep, maxb, (unsigned long)usb_ep[idx].buff,usb_ep[idx].bytes));
+    if ( !usb_ep[idx].bytes) pdiWriteEndpoint( usb_ep[idx].ep, 0, 0);
+    else {
+      if ( usb_ep[idx].bytes > maxb) {
+        pdiWriteEndpoint( usb_ep[idx].ep, maxb, usb_ep[idx].buff);
+        usb_ep[idx].bytes -= maxb;
+        usb_ep[idx].buff += maxb;
+      } else {
+        pdiWriteEndpoint( usb_ep[idx].ep, usb_ep[idx].bytes, usb_ep[idx].buff);
+        usb_ep[idx].buff += usb_ep[idx].bytes;
+        usb_ep[idx].bytes = 0;
+//        if ( usending) usending = 0;
+      }
+    }
+  }
+
+  unsigned char usb_receive_from_usb( unsigned char idx, unsigned char maxb) {
+    unsigned char ret = 0;
+
+    ret = (unsigned char)usb_ep[idx].bytes;
+    if ( !ret || ret > maxb) ret = maxb;
+    debugPrint( DBG_HIGH,("USB Receive EP#%d ->buff 0x%lX,cnt %d,(max %d)\n",usb_ep[idx].ep,(unsigned long)usb_ep[idx].buff,usb_ep[idx].bytes,ret));
+    if ( !usb_ep[idx].bytes) {
+//      ureceiving = 0;
+      pdiReadEndpoint( usb_ep[idx].ep, 0, 0);
+      return 0xff; // too_small_buffer error
+    }
+    do {
+      ret = pdiReadEndpoint( usb_ep[idx].ep, ret, usb_ep[idx].buff);
+      debugPrint( DBG_HIGH,(" - really readed %d\n", ret));
+      usb_ep[idx].buff += ret;
+      usb_ep[idx].bytes -= ret;
+    } while (( ret == maxb) && usb_ep[idx].bytes);
+    return ret;
+  }
+*/
+
+
+#ifdef DEBUG
+  char *ReqRecipient( char rqt) {
+    switch ( rqt & USB_RECIPIENT) {
+      case USB_RECIPIENT_DEVICE:    return "DEVICE";
+      case USB_RECIPIENT_INTERFACE: return "INTERFACE";
+      case USB_RECIPIENT_ENDPOINT:  return "ENDPOINT";
+    }
+    return "OTHER";
+  }
+  char *ReqType( char rqt) {
+    switch ( rqt & USB_REQUEST_TYPE_MASK) {
+      case USB_STANDARD_REQUEST: return "STANDARD";
+      case USB_CLASS_REQUEST:    return "CLASS";
+      case USB_VENDOR_REQUEST:   return "VENDOR";
+    }
+    return "RESERVED";
+  }
+  char *ReqName( char req) {
+    switch ( req & USB_REQUEST_MASK) {
+      case USB_REQUEST_GET_STATUS:        return "GET STATUS";
+      case USB_REQUEST_CLEAR_FEATURE:     return "CLEAR FEATURE";
+      case USB_REQUEST_SET_FEATURE:       return "SET FEATURE";
+      case USB_REQUEST_SET_ADDRESS:       return "SET ADDRESS";
+      case USB_REQUEST_GET_DESCRIPTOR:    return "GET DESCRIPTOR";
+      case USB_REQUEST_SET_DESCRIPTOR:    return "SET DESCRIPTOR";
+      case USB_REQUEST_GET_CONFIGURATION: return "GET CONFIGURATION";
+      case USB_REQUEST_SET_CONFIGURATION: return "SET CONFIGURATION";
+      case USB_REQUEST_GET_INTERFACE:     return "GET INTERFACE";
+      case USB_REQUEST_SET_INTERFACE:     return "SET INTERFACE";
+      case USB_REQUEST_SYNC_FRAME:        return "SYNC FRAME";
+    }
+    return "UNKNOWN";
+  }
+#endif
+
+
+  void usb_set_control_data(usb_control_ep_t *ep, void *buff, int size)
+  {
+    ep->data = (unsigned char *) buff;
+    ep->bytes = size;
+    usb_flags.request = 2;
+    debugPrint( DBG_HIGH,("usb_set_control_data buff=0x%lx, len=%d\n", (long)buff, size));
+  }
+
+  void usb_set_control_ack(usb_control_ep_t *ep)
+  {
+    ep->data = NULL;
+    ep->bytes = 0;
+    usb_flags.request = 3;
+    debugPrint( DBG_HIGH,("usb_set_control_ack\n"));
+  }
+  
+
+ /*
+  ***********************************
+  ***   Execute device requests   ***
+  ***********************************
+  */
+  void usb_answer_to_request( void) {
+    USB_DEVICE_REQUEST *pdreq = &usb_rxtx_control.dreq;
+    
+    debugPrint( DBG_MEDIUM,("Process usb setup packet\n"));
+    usb_rxtx_control.req_size=pdiReadEndpoint( PDI_EP0_RX, 255, (unsigned char *)pdreq);
+    if ( usb_rxtx_control.req_size == 0xff) {
+      /*LEDr = 1; SetLeds( hlp[0]);*/
+      debugPrint( DBG_LOW,("! BIG Setup packet\n"));
+      usb_stall_ep0();
+      return;
+    }
+    pdiAckSetupControl();
+    /* !!! it must be here !!! */
+    pdreq->wValue = SWAP( pdreq->wValue);
+    pdreq->wIndex = SWAP( pdreq->wIndex);
+    pdreq->wLength = SWAP( pdreq->wLength);
+
+    usb_rxtx_control.next_pkt_fnc = NULL;
+    usb_rxtx_control.complete_fnc = NULL;
+
+    ctrl_data[0] = ctrl_data[1] = 0; // we need only 2 bytes
+
+    #ifdef DEBUG
+      debugPrint( DBG_HIGH, ("Receive (0x%X) %s req. for %s , data %s host\n", 
+                  pdreq->bmRequestType, ReqType( pdreq->bmRequestType), 
+                  ReqRecipient(pdreq->bmRequestType),
+                  ((pdreq->bmRequestType & USB_DATA_DIR_MASK) ? "TO":"FROM")));
+      debugPrint( DBG_HIGH, ("   Request (0x%X) %s\n", pdreq->bRequest, 
+                  ((!(pdreq->bmRequestType&USB_REQUEST_TYPE_MASK))? ReqName( pdreq->bRequest):"UNKNOWN")));
+    #endif
+    
+    switch( pdreq->bmRequestType & USB_RECIPIENT) {
+      case USB_RECIPIENT_DEVICE:
+        switch( pdreq->bmRequestType & USB_REQUEST_TYPE_MASK) {
+          case USB_STANDARD_REQUEST:
+            switch( pdreq->bRequest) {
+              case USB_REQUEST_GET_STATUS:
+                #ifdef USB_MY_SELF_POWER 
+                  ctrl_data[0]=1;
+                #else 
+                  ctrl_data[0]=0;
+                #endif
+                USB_SET_CONTROL_DATA( &ctrl_data, 2);
+                //pdiWriteEndpoint( PDI_EP0_TX, 2, hlp);
+                break;
+              case USB_REQUEST_SET_ADDRESS:
+                usb_address = ( unsigned char)( pdreq->wValue & DEVICE_ADDRESS_MASK);
+                pdiSetAddressEnable( usb_address | PDI_ENAD_ENABLE);
+                USB_SET_CONTROL_ACK;
+                //pdiWriteEndpoint( PDI_EP0_TX, 0, 0);
+                break;
+              case USB_REQUEST_GET_DESCRIPTOR:
+                usb_get_descriptor();
+                break;
+              case USB_REQUEST_GET_CONFIGURATION:
+                if ( usb_flags.configured) ctrl_data[0] = 1;
+                USB_SET_CONTROL_DATA( &ctrl_data, 1);
+                //pdiWriteEndpoint( PDI_EP0_TX, 1, hlp);
+                break;
+              case USB_REQUEST_SET_CONFIGURATION:
+                if (LSB( pdreq->wValue) < 2) {
+                  if ( LSB( pdreq->wValue)) {
+                    pdiSetEndpointEnable( usb_flags.configured=1);
+                  } else {
+                    pdiSetEndpointEnable( usb_flags.configured=0);
+                  }
+                  USB_SET_CONTROL_ACK;
+                  //pdiWriteEndpoint( PDI_EP0_TX, 0, 0);
+                } else
+                  usb_stall_ep0();
+                break;                
+              default:
+                usb_stall_ep0();
+                break;
+            }
+
+            break;
+          case USB_VENDOR_REQUEST:
+           if(usb_vendor_extension) {
+             int ret;
+             ret = usb_vendor_extension(&usb_rxtx_control, pdreq);
+             if (ret<0) {
+               usb_stall_ep0();
+               break;
+             }
+             if (ret>0) {
+               break;
+             }
+           }
+         
+            switch ( pdreq->bRequest) {
+              case USB_VENDOR_START_TRANSFER:
+                {
+                  unsigned long max = ((long)pdreq->wIndex << 16)+pdreq->wValue;
+                  usb_rx_bulk.remain = ( usb_rx_bulk.bytes < max) ? usb_rx_bulk.bytes : max;
+                }
+                USB_SET_CONTROL_ACK;
+               break;
+              case USB_VENDOR_CONTROL_TERMINAL_MODE:
+                if ( pdreq->wValue == 1) usb_flags.terminal_mode = 1;
+                else usb_flags.terminal_mode = 0;
+                USB_SET_CONTROL_ACK;
+               break;
+              default:
+                USB_SET_CONTROL_ACK;
+                //pdiWriteEndpoint( PDI_EP0_TX, 0, 0);
+                break;
+            }            
+            break;            
+          case USB_CLASS_REQUEST:
+            usb_stall_ep0();
+          default:
+            usb_stall_ep0();
+            break;
+        }
+        break;
+      case USB_RECIPIENT_INTERFACE:
+        if (( pdreq->bmRequestType & USB_REQUEST_TYPE_MASK) == USB_STANDARD_REQUEST) {
+          switch( pdreq->bRequest) {
+            case USB_REQUEST_GET_STATUS:
+              USB_SET_CONTROL_DATA( &ctrl_data, 2);
+              //pdiWriteEndpoint( PDI_EP0_TX, 2, hlp);
+              break;
+            case USB_REQUEST_GET_INTERFACE:
+              debugPrint( DBG_HIGH,("ReqIfc=%d Now ifc=%d\n", pdreq->wIndex, usb_interface));
+              USB_SET_CONTROL_DATA( &ctrl_data, 1); // alternate interface
+              //pdiWriteEndpoint( PDI_EP0_TX, 1, hlp);
+              break;
+            case USB_REQUEST_SET_INTERFACE:
+              //if (( dreq.wValue == 0) && ( dreq.wIndex == 0))
+              if ( pdreq->wIndex < 1) { // mame jen 2 pokusne interface
+                usb_interface = (unsigned char) pdreq->wIndex;
+                USB_SET_CONTROL_ACK;
+                //pdiWriteEndpoint( PDI_EP0_TX, 0, 0);
+              } else
+                usb_stall_ep0();
+              break;
+            default:
+              usb_stall_ep0();                          
+          }
+        } else
+          usb_stall_ep0();
+        break;
+      case USB_RECIPIENT_ENDPOINT:
+        if (( pdreq->bmRequestType & USB_REQUEST_TYPE_MASK) == USB_STANDARD_REQUEST) {
+          switch( pdreq->bRequest) {
+            case USB_REQUEST_GET_STATUS:
+            case USB_REQUEST_CLEAR_FEATURE:
+            case USB_REQUEST_SET_FEATURE:
+              {
+                ctrl_data[0] = ( unsigned char)(( pdreq->wIndex & PDI_CNT_EP)<<1);
+                if ( pdreq->wIndex & ( unsigned char) USB_ENDPOINT_DIRECTION_MASK)
+                  ctrl_data[0]++;
+                if ( pdreq->bRequest == USB_REQUEST_GET_STATUS) {
+                  ctrl_data[0] = pdiSelectEp( ctrl_data[0]); // endpoint in
+                  ctrl_data[0] = (( ctrl_data[0] & PDI_SELEP_STALL) == PDI_SELEP_STALL);
+                  USB_SET_CONTROL_DATA( &ctrl_data, 2);
+                  //pdiWriteEndpoint( PDI_EP0_TX, 2, hlp);
+                } else {
+                  if ( pdreq->bRequest == USB_REQUEST_CLEAR_FEATURE) {
+                    pdiSetEpStatus( ctrl_data[0], 0);
+                    //pdiWriteEndpoint( PDI_EP0_TX, 0, 0);
+                  } else {
+                    pdiSetEpStatus( ctrl_data[0], 1);
+                    //pdiWriteEndpoint( PDI_EP0_TX, 0, 0);
+                  }
+                  USB_SET_CONTROL_ACK;
+                }
+              }
+              break;
+            default:
+              usb_stall_ep0();
+          }
+        } else 
+          usb_stall_ep0();
+        break;
+//      case USB_RECIPIENT_OTHER:
+      default:
+        usb_stall_ep0();
+        break;
+    }
+//    usb_flags.command = 0; // ??? data or ack stage ???
+
+#ifdef USE_USB_WITH_IRQ
+// send data if it is needed
+      if ( usb_flags.request == 2) { // request is set to data stage
+        if (( usb_rxtx_control.dreq.bmRequestType & USB_DATA_DIR_MASK)==USB_DATA_DIR_TO_HOST) {
+          unsigned int now = usb_rxtx_control.bytes;
+          if ( now > PDI_EP0_PACKET_SIZE) now = PDI_EP0_PACKET_SIZE;
+         if ( usb_rxtx_control.next_pkt_fnc )
+           if( usb_rxtx_control.next_pkt_fnc(&usb_rxtx_control, now, USB_NEXT_PKT_SEND) ) {
+              usb_stall_ep0();
+             return;
+           }
+          debugPrint( DBG_HIGH, ("CNTR send 1.data (%d)\n", now));
+          pdiWriteEndpoint( PDI_EP0_TX, now, usb_rxtx_control.data);
+          usb_rxtx_control.data += now;
+          if ( !(usb_rxtx_control.bytes -= now)) {
+            usb_flags.request = 3;
+          }
+        }
+      }
+      if ( usb_flags.request == 3) {
+        if ( !usb_rxtx_control.dreq.wLength ||
+             (usb_rxtx_control.dreq.bmRequestType & USB_DATA_DIR_MASK)==USB_DATA_DIR_FROM_HOST) {
+          pdiWriteEndpoint( PDI_EP0_TX, 0, 0);
+         if ( usb_rxtx_control.complete_fnc )
+           usb_rxtx_control.complete_fnc(&usb_rxtx_control, USB_COMPLETE_OK);
+         usb_rxtx_control.next_pkt_fnc = NULL;
+         usb_rxtx_control.complete_fnc = NULL;
+        }
+      }
+#endif
+  }
+
+#ifdef DEBUG
+  char *DescType( unsigned char desc) {
+    switch ( desc) {
+      case USB_DESCRIPTOR_TYPE_DEVICE:                    return"DEVICE";
+      case USB_DESCRIPTOR_TYPE_CONFIGURATION:             return"CONFIGURATION";
+      case USB_DESCRIPTOR_TYPE_STRING:                    return"STRING";
+      case USB_DESCRIPTOR_TYPE_INTERFACE:                 return"INTERFACE";
+      case USB_DESCRIPTOR_TYPE_ENDPOINT:                  return"ENDPOINT";
+      case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER:          return"DEVICE_QUALIFIER";
+      case USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION: return"OTHER_SPEED_CONFIG";
+      case USB_DESCRIPTOR_TYPE_POWER:                     return"POWER";
+    }
+    return "UNKNOWN";
+  }
+#endif
+
+  void usb_get_descriptor( void) {
+    unsigned int size;
+    unsigned short wVal = usb_rxtx_control.dreq.wValue;
+    debugPrint( DBG_MEDIUM, (" - %s descriptor\n", DescType(MSB( wVal))));
+    switch ( MSB( wVal)) {
+      case USB_DESCRIPTOR_TYPE_DEVICE:
+        usb_rxtx_control.data = (unsigned char *) &usb_device_descriptor;
+        size = sizeof( USB_DEVICE_DESCRIPTOR);
+        break;
+      case USB_DESCRIPTOR_TYPE_CONFIGURATION:
+        usb_rxtx_control.data  = (unsigned char *) &usb_config_0;
+        size = CONFIG_0_DESCRIPTOR_LENGTH;
+        break;
+      case USB_DESCRIPTOR_TYPE_STRING:
+        if ( LSB( wVal) < USB_CNT_STRINGS) {
+          usb_rxtx_control.data  = (unsigned char *) StringDescriptors[ LSB( wVal)];
+          size = *usb_rxtx_control.data;
+        } else {
+          usb_stall_ep0();
+          return;
+        }
+        break;
+      default:
+        usb_stall_ep0();
+        return;
+    }    
+    usb_rxtx_control.bytes = ( usb_rxtx_control.dreq.wLength < size) ? usb_rxtx_control.dreq.wLength : size;
+    usb_flags.request = 2;
+    //usb_send_to_usb( SEND_EP0, PDI_EP0_PACKET_SIZE);
+  }
+
+
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+/***                                                                       ***/
+/*** USB with IRQ                                                          ***/
+/***                                                                       ***/
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+
+ #ifdef PDIUSB_WITH_EXCPTVECT_SET
+  void usb_isr(void)
+ #else /*PDIUSB_WITH_EXCPTVECT_SET*/
+  void usb_isr(int intno, void *dev_id, struct pt_regs *regs)
+ #endif /*PDIUSB_WITH_EXCPTVECT_SET*/
+  {
+    unsigned char usb_last_status;
+    
+    usb_irq_cnt++;    
+    usb_last_irq = pdiGetInterrupt();
+    if ( usb_last_irq) {
+      usb_flags.was_int = 1;
+      
+      debugPrint( DBG_INT, ("USB Interrupt 0x%X\n",usb_last_irq));
+      if ( usb_last_irq & PDI_INT_BUSRESET) {                  // D12 - Bus reset reached
+        usb_flags.configured = 0;
+        if ( usb_flags.running && usb_flags.stop_request) {
+          usb_flags.running = 0;
+          usb_flags.stop_request = 0;
+        }
+        debugPrint( DBG_INT, ("Bus Reset\n"));
+      } else {
+        if ( usb_last_irq & PDI_INT_SUSPEND) {            // D12 - Suspend flag changed
+          debugPrint( DBG_INT, ("Suspend Changed\n"));
+        }
+        // it must be first b/c tx and rx can be sended all together
+        if ( usb_last_irq & PDI_INT_EP0_IN) {                 // D12 - Ep0TxDone - data in EP0 was sended
+          usb_last_status = pdiGetLastTransStatus( PDI_EP0_TX);
+          debugPrint( DBG_INT, ("Ep0-Tx LTS=0x%X\n", usb_last_status));    
+          if (( usb_last_status & PDI_LTSTAT_RXTX_OK) && usb_flags.request > 1) {
+            if ( usb_flags.request == 2) {
+              unsigned int now = usb_rxtx_control.bytes;
+              if ( now > PDI_EP0_PACKET_SIZE) now = PDI_EP0_PACKET_SIZE;
+              debugPrint( DBG_INT, ("CNTR data\n"));
+              pdiWriteEndpoint( PDI_EP0_TX, now, usb_rxtx_control.data);
+              usb_rxtx_control.data += now;
+              if ( !(usb_rxtx_control.bytes -= now)) {
+                usb_flags.request = 3;
+              }
+            } else if ( usb_flags.request == 3) {
+              debugPrint( DBG_INT, ("CNTR ack\n"));
+              usb_flags.request = 0;
+            } else {
+              debugPrint( DBG_INT, ("tx 0 ... ???\n"));
+            }
+          }
+        }
+        
+        if ( usb_last_irq & PDI_INT_EP0_OUT) {                // D12 - Ep0RxDone - some data was received in EP0
+          usb_last_status = pdiGetLastTransStatus( PDI_EP0_RX);
+          debugPrint( DBG_INT, ("Ep0-Rx LTS=0x%X\n", usb_last_status));
+          if ( usb_last_status & PDI_LTSTAT_RXTX_OK) {
+            if ( usb_last_status & PDI_LTSTAT_SETUP) {
+              if ( usb_flags.request) {
+                debugPrint( DBG_INT, ("!!! New setup, but last not ack ...\n"));
+              }
+              usb_flags.request = 1; // Standard_requests();
+              usb_answer_to_request();
+            } else {
+              if ( usb_flags.request == 2) {
+                unsigned int now = usb_rxtx_control.bytes, ret;
+                if ( now > PDI_EP0_PACKET_SIZE) now = PDI_EP0_PACKET_SIZE;
+                debugPrint( DBG_INT, ("CNTR data\n"));
+                ret = pdiReadEndpoint( PDI_EP0_RX, now, usb_rxtx_control.data);
+
+               if(ret>usb_rxtx_control.bytes)
+                 ret = usb_rxtx_control.bytes;
+
+                usb_rxtx_control.data += ret;
+
+               if ( usb_rxtx_control.next_pkt_fnc ) {
+                 if( usb_rxtx_control.next_pkt_fnc(&usb_rxtx_control, ret, USB_NEXT_PKT_REC) ) {
+                    usb_stall_ep0();
+                 }
+               }
+
+                if (!(usb_rxtx_control.bytes -= ret)) {
+                  usb_rxtx_control.data -= usb_rxtx_control.dreq.wLength;
+                  usb_flags.request = 3;
+                }
+              } else if ( usb_flags.request == 3) {
+                debugPrint( DBG_INT, ("CNTR ack\n"));
+                usb_flags.request = 0;
+                pdiReadEndpoint( PDI_EP0_RX, 0, 0);
+               if ( usb_rxtx_control.complete_fnc )
+                 usb_rxtx_control.complete_fnc(&usb_rxtx_control, USB_COMPLETE_OK);
+               usb_rxtx_control.next_pkt_fnc = NULL;
+               usb_rxtx_control.complete_fnc = NULL;
+              } else {
+                pdiReadEndpoint( PDI_EP0_RX, 0, 0);
+              }
+            }
+          }
+        }
+        if ( usb_last_irq & PDI_INT_EP1_OUT) {                // D12 - Ep1RxDone - some data was received in EP1
+          usb_last_status = pdiGetLastTransStatus( PDI_EP1_RX);
+          debugPrint( DBG_INT, ("Ep1-Rx LTS=0x%X\n", usb_last_status));
+          if ( usb_last_status & PDI_LTSTAT_RXTX_OK) {
+            pdiSetEpStatus( PDI_EP1_OUT, PDI_SET_EP_STALLED);
+          }
+        }
+        if ( usb_last_irq & PDI_INT_EP1_IN) {                 // D12 - Ep1TxDone - data in EP1 was sended
+          usb_last_status = pdiGetLastTransStatus( PDI_EP1_TX);
+          debugPrint( DBG_INT, ("Ep1-Tx LTS=0x%X\n", usb_last_status));
+          if ( usb_last_status & PDI_LTSTAT_RXTX_OK) {
+            pdiSetEpStatus( PDI_EP1_IN, PDI_SET_EP_STALLED);
+          }
+        }
+
+        if ( usb_last_irq & PDI_INT_EP2_OUT) {                // D12 - Ep2RxDone - some data was received in EP2
+          usb_last_status = pdiGetLastTransStatus( PDI_EP2_RX);
+          debugPrint( DBG_INT, ("Ep2-Rx LTS=0x%X\n", usb_last_status));
+          if ( usb_last_status & PDI_LTSTAT_RXTX_OK) {
+            if ( usb_flags.terminal_mode) {
+              unsigned char hlpbfr[PDI_EP2_PACKET_SIZE], now = PDI_EP2_PACKET_SIZE, i;
+            MoreRead:
+              now = pdiReadEndpoint( PDI_EP2_RX, now, hlpbfr);
+              for(i=0;i<now;i++) {
+                usb_tm_rcv++;
+                if (usb_com_put( &usb_com_que_in, hlpbfr[i])<0) { /* nevkladat dalsi */
+                  break;
+                }
+              }
+              if(now==PDI_EP2_PACKET_SIZE) goto MoreRead;              
+            } else {
+              unsigned char now = (usb_rx_bulk.remain > (unsigned long)PDI_EP2_PACKET_SIZE)?PDI_EP2_PACKET_SIZE:(unsigned char)usb_rx_bulk.remain;
+  //            unsigned char hlp[2];            
+                
+                if ( !usb_flags.bits.bulk_rx_data) {
+                  usb_flags.bulk_rx_data = 1;
+                  usb_start = msec_time;
+                }
+  //              if ( now > PDI_EP2_PACKET_SIZE) now = PDI_EP2_PACKET_SIZE;
+              ReadAgain:
+                now = pdiReadEndpoint( PDI_EP2_RX, now, usb_rx_bulk.data);
+                usb_rx_bulk.data += now;
+                if ( !( usb_rx_bulk.remain -= now)) {
+                  usb_stop = msec_time;
+                  usb_flags.bulk_rx_data = 0;
+                // complete_func or set flag(event)
+                }
+              if ( usb_rx_bulk.remain > 0 && usb_rx_bulk.remain <= PDI_EP2_PACKET_SIZE) 
+                goto ReadAgain;
+            }  
+          }
+        }
+        if ( usb_last_irq & PDI_INT_EP2_IN) {                 // D12 - Ep2TxDone - data in EP2 was sended
+          usb_last_status = pdiGetLastTransStatus( PDI_EP2_TX);
+          debugPrint( DBG_INT, ("Ep2-Tx LTS=0x%X\n", usb_last_status));
+          if ( usb_last_status & PDI_LTSTAT_RXTX_OK) {
+            if ( usb_flags.terminal_mode) {              
+              int ch;
+              usb_tm_snded++;
+              ch = usb_com_get( &usb_com_que_out);
+              if ( ch < 0) {
+                usb_flags.bulk_tx_data = 0;
+              } else {
+                unsigned char uchr = ch;                
+                usb_flags.bulk_tx_data = 1;
+                pdiWriteEndpoint( PDI_EP2_TX, 1, &uchr);
+              }
+            } else {
+              if ( usb_tx_bulk.remain) {
+                unsigned int now = usb_tx_bulk.remain;
+                if ( now > PDI_EP2_PACKET_SIZE) now = PDI_EP2_PACKET_SIZE;
+                pdiWriteEndpoint( PDI_EP2_TX, now, usb_tx_bulk.data);
+                usb_tx_bulk.data += now;
+                if (!(usb_tx_bulk.remain -= now)) {
+                  // complete_func or set flag(event)
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+#ifdef PDIUSB_WITH_ADD_IRQ_HANDLER
+  irq_handler_t usb_irq_handler = {
+    handler: usb_isr,
+    flags:   0,
+    dev_id:  0,
+    devname: "usb",
+    next:    0
+  };
+#endif /*PDIUSB_WITH_ADD_IRQ_HANDLER*/
+
+  
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+/***                                                                       ***/
+/*** USB COM Emulator Module                                               ***/
+/***                                                                       ***/
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/ 
+  int usb_tm_snd;
+  int usb_tm_snded;
+  int usb_tm_rcv;
+
+  int usb_com_init( void) {        
+    usb_tm_snd = 0;
+    usb_tm_snded = 0;
+    usb_tm_rcv = 0;
+    
+    usb_com_que_in.begin=usb_com_buf_in;
+    usb_com_que_in.end=usb_com_que_in.begin+sizeof(usb_com_buf_in);
+    usb_com_que_in.first=usb_com_que_in.begin;
+    usb_com_que_in.last=usb_com_que_in.begin;
+  
+    usb_com_que_out.begin=usb_com_buf_out;
+    usb_com_que_out.end=usb_com_que_out.begin+sizeof(usb_com_buf_out);
+    usb_com_que_out.first=usb_com_que_out.begin;
+    usb_com_que_out.last=usb_com_que_out.begin;
+  
+    return 1;
+  }
+
+  /* put character c into queue, if full return -1 */
+  int usb_com_put(usb_com_que_t *q, int c)
+  {
+    unsigned char *p=q->last;
+    *(p++)=(unsigned char)c;
+    if (p==q->end) p=q->begin;
+    if (p==q->first) return -1;
+    q->last=p;
+    return c;
+  }
+  /* get character from queue, if empty return -1 */
+  int usb_com_get(usb_com_que_t *q)
+  {
+    unsigned char *p;
+    int c;
+    p=q->first;
+    if(p==q->last) return -1;
+    c=*(p++);
+    if(p==q->end) p=q->begin;
+    q->first=p;
+    return c;
+  }
+
+/*
+  int usb_com_sendch(int c) {
+    if ( usb_flags.terminal_mode) {
+      usb_tm_snd++;
+      if ( !usb_flags.bits.bulk_tx_data) { // hned poslat - atomicke nastaveni flagu ... 
+        unsigned char byte = c;
+        pdiWriteEndpoint( PDI_EP2_TX, 1, (unsigned char *)&byte);
+        usb_flags.bulk_tx_data = 1; 
+      } else {        
+        if( usb_com_put(&usb_com_que_out,c)<0){ // nevejde se 
+#ifdef USE_USB_WITH_IRQ 
+          while( usb_com_que_out.last == usb_com_que_out.first-1); // Wait if buffer is full !@#$%^&* 
+          if( usb_com_put(&usb_com_que_out,c)<0)                   // case (last==end and first==begin) not respected 
+#endif
+            c=-1;
+        }
+      }
+    }
+    return c;
+  }
+*/  
+  void usb_com_start_send( void) {
+    if ( !usb_flags.bits.bulk_tx_data &&
+         usb_com_que_out.first != usb_com_que_out.last) {
+      int ch;
+      ch = usb_com_get( &usb_com_que_out);
+      if ( ch >= 0) {
+        unsigned char byte = ch;
+        usb_flags.bulk_tx_data = 1;
+        pdiWriteEndpoint( PDI_EP2_TX, 1, &byte);
+      }
+    }
+  }
+  
+  int usb_com_sendch(int c) {
+    if ( usb_flags.terminal_mode) {
+      usb_tm_snd++;
+#ifndef USE_USB_WITH_IRQ
+      if( !usb_flags.bits.bulk_tx_data) {
+        unsigned char byte = c;
+        usb_flags.bulk_tx_data = 1;
+        pdiWriteEndpoint( PDI_EP2_TX, 1, &byte);        
+        return c;
+      }
+#endif
+      if( usb_com_put(&usb_com_que_out,c)<0){ /* nevejde se */
+      
+#ifdef USE_USB_WITH_IRQ 
+        if ( !usb_flags.bits.bulk_tx_data) {
+          usb_com_start_send();
+        } else {
+          while( usb_com_que_out.last == usb_com_que_out.first-1); /* Wait if buffer is full !@#$%^&* */
+        }
+        if( usb_com_put(&usb_com_que_out,c)<0)                   /* case (last==end and first==begin) isn't respected */
+#endif
+          c=-1;
+      }
+    }
+    return c;
+  }
+  
+  
+  
+  int usb_com_recch() {
+    int val;
+    if ( !usb_flags.bits.terminal_mode) return -1;
+    val=usb_com_get(&usb_com_que_in);
+    return val;
+  }
+  
+  int usb_com_sendstr(const char *s) {
+    int cnt=0;
+    while(*s)
+    {
+      if(usb_com_sendch((unsigned char)(*(s++)))<0) break;
+      cnt++;
+    }
+    return cnt;    
+  }
+  
diff --git a/embedded/libs4c/usb/more/usb_srq.c b/embedded/libs4c/usb/more/usb_srq.c
new file mode 100644 (file)
index 0000000..463f039
--- /dev/null
@@ -0,0 +1,224 @@
+/*****************************************************/
+/***   Module : USB module                         ***/
+/***   Author : Roman Bartosinski (C) 28.04.2002   ***/
+/***   Modify : 08.08.2002, 16.04.2003             ***/
+/*****************************************************/
+
+#include <string.h>
+
+#include <system_def.h>
+#include <usb/usb.h>
+#include <usb/usb_spec.h>
+#include <usb/pdiusb.h>
+#include <usb/usbdebug.h>
+#include <usb/usb_srq.h>
+#include <usb/usb_defs.h>
+
+  // ****************************
+  int usb_stdreq_get_status( usb_device_t *udev)
+  {
+    unsigned char c, buf[2] = { 0, 0};
+    unsigned char epid = (unsigned char) udev->request.wIndex;
+
+    usb_debug_print( DEBUG_LEVEL_HIGH, ("GetStatus\n"));
+    switch( udev->request.bmRequestType & USB_RECIPIENT) {
+      case USB_RECIPIENT_DEVICE:
+        if ( udev->flags & USB_FLAG_REMOTE_WAKE) //.remote_wake_up == 1)
+          buf[0] = USB_GETSTATUS_REMOTE_WAKEUP_ENABLED | USB_GETSTATUS_SELF_POWERED;
+        else
+          buf[0] = USB_GETSTATUS_SELF_POWERED;
+        break;
+      case USB_RECIPIENT_INTERFACE:
+        break;
+      case USB_RECIPIENT_ENDPOINT:
+        if ( epid & USB_ENDPOINT_DIRECTION_MASK)
+          c = pdiSelectEp(pdiEp2Idx(epid)); // endpoint in
+        else
+          c = pdiSelectEp(pdiEp2Idx(epid));     // endpoint Out
+          #ifdef PDIUSBD12
+          buf[0] = (( c & PDI_SELEP_STALL) == PDI_SELEP_STALL);
+          #else
+          buf[0] = 0;
+          #endif
+        break;
+      default:
+        return USB_COMPLETE_FAIL;
+    }
+    pdiWriteEndpoint( PDI_EP0_TX, 2, buf);
+    return USB_COMPLETE_OK;
+  }
+
+  int usb_stdreq_clear_feature( usb_device_t *udev)
+  {
+    USB_DEVICE_REQUEST *dreq = &(udev->request);
+    unsigned char epid = (unsigned char) dreq->wIndex;
+
+    usb_debug_print( DEBUG_LEVEL_HIGH, ("ClearFeature\n"));
+    switch( dreq->bmRequestType & USB_RECIPIENT) {
+      case USB_RECIPIENT_DEVICE:
+        if ( dreq->wValue == USB_FEATURE_REMOTE_WAKEUP) {
+          udev->flags &= ~USB_FLAG_REMOTE_WAKE; //.remote_wake_up = 0;
+          usb_udev_ack_setup( udev);
+          return USB_COMPLETE_OK;
+        }
+        break;
+      case USB_RECIPIENT_ENDPOINT:
+        if ( dreq->wValue == USB_FEATURE_ENDPOINT_STALL) {
+          if ( epid & USB_ENDPOINT_DIRECTION_MASK)
+            pdiSetEpStatus(pdiEp2Idx(epid), 0); // clear TX stall for IN on EPn
+          else
+            pdiSetEpStatus(pdiEp2Idx(epid), 0); // clear RX stall for OUT on EPn
+          usb_udev_ack_setup( udev);
+          return USB_COMPLETE_OK;
+        }
+        break;
+    }
+    return USB_COMPLETE_FAIL;
+  }
+
+  int usb_stdreq_set_feature( usb_device_t *udev)
+  {
+    USB_DEVICE_REQUEST *dreq = &(udev->request);
+    unsigned char epid = (unsigned char) dreq->wIndex;
+
+    usb_debug_print( DEBUG_LEVEL_HIGH, ("SetFeature\n"));
+    switch( dreq->bmRequestType & USB_RECIPIENT) {
+      case USB_RECIPIENT_DEVICE:
+        if ( dreq->wValue == USB_FEATURE_REMOTE_WAKEUP) {
+          udev->flags |= USB_FLAG_REMOTE_WAKE; //.remote_wake_up = 1;
+          usb_udev_ack_setup( udev);
+          return USB_COMPLETE_OK;
+        }
+        break;
+      case USB_RECIPIENT_ENDPOINT:
+        if ( dreq->wValue == USB_FEATURE_ENDPOINT_STALL) {
+          if ( epid & USB_ENDPOINT_DIRECTION_MASK)
+            pdiSetEpStatus( pdiEp2Idx(epid), 1); // set TX stall for IN on EPn
+          else
+            pdiSetEpStatus( pdiEp2Idx(epid), 1);     // set RX stall for OUT on EPn
+          usb_udev_ack_setup( udev);
+          return USB_COMPLETE_OK;
+        }
+        break;
+    }
+    return USB_COMPLETE_FAIL;
+  }
+
+  int usb_stdreq_set_address( usb_device_t *udev)
+  {
+    USB_DEVICE_REQUEST *dreq = &(udev->request);
+    usb_debug_print( DEBUG_LEVEL_HIGH, ("SetAddr\n"));
+    usb_udev_ack_setup( udev);
+    pdiSetAddressEnable( (dreq->wValue & DEVICE_ADDRESS_MASK) + PDI_ENAD_ENABLE);
+    return USB_COMPLETE_OK;
+  }
+
+  int usb_stdreq_get_configuration( usb_device_t *udev)
+  {
+    unsigned char buf = udev->configuration; //usb_flags.configured;
+    usb_debug_print( DEBUG_LEVEL_HIGH, ("GetConfig\n"));
+    pdiWriteEndpoint( PDI_EP0_TX, 1, &buf);
+    return USB_COMPLETE_OK;
+  }
+
+  int usb_stdreq_set_configuration( usb_device_t *udev)
+  {
+    USB_DEVICE_REQUEST *dreq = &(udev->request);
+    unsigned char iCfg = dreq->wValue & 0xff;
+    usb_debug_print( DEBUG_LEVEL_HIGH, ("SetConfig\n"));
+    if ( iCfg < 2) {       // put device in unconfigured state or set configuration 1 ( no else)
+      usb_udev_ack_setup( udev);
+      pdiSetEndpointEnable( 0); // USBInitUnconfig();
+      if ( iCfg) {
+        pdiSetEndpointEnable( PDI_EPEN_ENABLE); //USBInitConfig();
+        udev->flags |= USB_FLAG_CONFIGURED;
+      } else {
+        udev->flags &= ~USB_FLAG_CONFIGURED;
+      }
+      udev->configuration = iCfg;  //usb_flags.configured = iCfg;
+      return USB_COMPLETE_OK;
+    } else
+      return USB_COMPLETE_FAIL;
+  }
+
+  int usb_stdreq_get_interface( usb_device_t *udev)
+  {
+    unsigned char buf = 0; /// udev->interface
+    usb_debug_print( DEBUG_LEVEL_HIGH, ("GetIface\n"));
+    pdiWriteEndpoint( PDI_EP0_TX, 1, &buf);
+    return USB_COMPLETE_OK;
+  }
+
+  int usb_stdreq_set_interface( usb_device_t *udev)
+  {
+    USB_DEVICE_REQUEST *dreq = &(udev->request);
+    
+    usb_debug_print( DEBUG_LEVEL_HIGH, ("SetIface\n"));
+    if (( dreq->wValue == 0) && ( dreq->wIndex == 0)) {
+      usb_udev_ack_setup( udev);
+      return USB_COMPLETE_OK;
+    } else {
+      return USB_COMPLETE_FAIL;
+    }
+  }
+
+  int usb_stdreq_get_descriptor( usb_device_t *udev)
+  {
+    unsigned char *pDesc;
+    unsigned short Len = 0;
+    USB_DEVICE_REQUEST *dreq = &(udev->request);
+    int i;
+
+    i = (dreq->wValue >> 8) & 0xff; /* MSB part of wValue */
+    usb_debug_print( DEBUG_LEVEL_HIGH, ("GetDesc\n"));
+    usb_debug_print( DEBUG_LEVEL_VERBOSE, ( " - %s desc.\n", /*(unsigned int)*/ usb_debug_get_std_descriptor(i)));
+
+    switch (i) {
+      case USB_DESCRIPTOR_TYPE_DEVICE:
+        pDesc = (unsigned char *)&DeviceDescription;
+        Len = sizeof( USB_DEVICE_DESCRIPTOR);
+        break;
+      case USB_DESCRIPTOR_TYPE_CONFIGURATION:
+        pDesc = (unsigned char *)&ConfigDescription;
+        Len = CONFIG_DESCRIPTOR_LENGTH;
+        break;
+      case USB_DESCRIPTOR_TYPE_INTERFACE:
+        pDesc = (unsigned char *)&ConfigDescription.interface;
+        Len = sizeof( USB_INTERFACE_DESCRIPTOR);
+        break;
+      case USB_DESCRIPTOR_TYPE_STRING:
+        i = dreq->wValue & 0xff; /* LSB part of wValue */
+        /*printf("Get descriptor indx=0x%02x\n", i);*/
+        if ( i < CNT_STRINGS) {
+          pDesc = (unsigned char *) StringDescriptors[ i];
+          Len = *pDesc;
+          /*usb_debug_print(0,("indx=0x%02x ptr=%p len=%d : '%c'\n", i, pDesc, Len, pDesc[2]));*/
+        } else {
+          return USB_COMPLETE_FAIL;
+        }
+        break;
+      default:
+        return USB_COMPLETE_FAIL;
+    }
+    if ( dreq->wLength < Len) Len = dreq->wLength;
+    usb_send_control_data( udev, pDesc, Len);
+    return USB_COMPLETE_OK;
+  }
+
+
+/*  
+  void usb_init_stdreq_fnc( usb_device_t *udev)
+  {
+    // memset( udev->stdreq, 0, sizeof(udev->stdreq));
+    
+    udev->stdreq[USB_REQUEST_GET_STATUS] = usb_stdreq_get_status;
+    udev->stdreq[USB_REQUEST_CLEAR_FEATURE] = usb_stdreq_clear_feature;
+    udev->stdreq[USB_REQUEST_SET_FEATURE] = usb_stdreq_set_feature;
+    udev->stdreq[USB_REQUEST_SET_ADDRESS] = usb_stdreq_set_address;
+    udev->stdreq[USB_REQUEST_GET_DESCRIPTOR] = usb_stdreq_get_descriptor;
+    udev->stdreq[USB_REQUEST_GET_CONFIGURATION] = usb_stdreq_get_configuration;
+    udev->stdreq[USB_REQUEST_SET_CONFIGURATION] = usb_stdreq_set_configuration;
+    udev->stdreq[USB_REQUEST_GET_INTERFACE] = usb_stdreq_get_interface;
+    udev->stdreq[USB_REQUEST_SET_INTERFACE] = usb_stdreq_set_interface;
+  }
+*/
diff --git a/embedded/libs4c/usb/pdiusb/Makefile b/embedded/libs4c/usb/pdiusb/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/embedded/libs4c/usb/pdiusb/Makefile.omk b/embedded/libs4c/usb/pdiusb/Makefile.omk
new file mode 100644 (file)
index 0000000..40b9dfd
--- /dev/null
@@ -0,0 +1,12 @@
+# -*- makefile -*-
+
+default_CONFIG = CONFIG_USB_PDIUSB=n
+
+ifeq ($(CONFIG_USB_PDIUSB),y) 
+lib_LIBRARIES = usbpdi
+
+nobase_include_HEADERS = usb/pdi.h usb/pdiusb.h
+
+usbpdi_SOURCES = pdi.c pdiusb.c
+#usbpdi_SOURCES +=  pdi4rtems.c
+endif #CONFIG_USB_PDIUSB
diff --git a/embedded/libs4c/usb/pdiusb/pdi.c b/embedded/libs4c/usb/pdiusb/pdi.c
new file mode 100644 (file)
index 0000000..3229d36
--- /dev/null
@@ -0,0 +1,201 @@
+/*****************************************************/
+/***   Module : USB PDI                            ***/
+/***   Author : Roman Bartosinski (C) 28.04.2002   ***/
+/***   Modify : 08.08.2002, 16.04.2003             ***/
+/*****************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <system_def.h>
+
+#define USB_PDI_EXPORT_FNC
+
+#include <usb/pdiusb.h>
+#include <usb/pdi.h>
+#include <usb/usbdebug.h>
+
+
+/* init chip state */
+  void pdiInitChipState( void) {
+   #ifdef PDIUSBD11
+    pdiSetHUBAddressEnable( 0, 0);
+   #endif /*PDIUSBD11*/
+    pdiSetAddressEnable( PDI_ENAD_ENABLE);
+    pdiSetEndpointEnable( PDI_EPEN_ENABLE);
+  }
+#ifdef PDIUSBD11
+
+  #define PDI_MODE_BASE_VALUE (PDI_MODE_MUSTBEONE | \
+  PDI_MODE_REMOTE_WAKEUP | PDI_MODE_NO_LAZY_CLOCK | \
+  PDI_MODE_CLOCK_RUNNING | PDI_CLOCK_4M)
+
+#else /*PDIUSBD11*/
+
+  #define PDI_MODE_BASE_VALUE (PDI_CLOCK_SET_TO_ONE | \
+  PDI_MODE_NO_LAZY_CLOCK | PDI_MODE_CLOCK_RUNNING | \
+  PDI_CLOCK_4M)
+
+#endif /*PDIUSBD11*/
+
+
+/* connect usb */
+  int usb_pdi_connect( usb_device_t *udev) {
+    pdiSetMode( PDI_MODE_BASE_VALUE | PDI_MODE_SOFT_CONNECT );
+    return 0;
+  }
+
+/* disconnect usb */
+  int usb_pdi_disconnect( usb_device_t *udev) {
+    pdiSetMode( PDI_MODE_BASE_VALUE & ~PDI_MODE_SOFT_CONNECT );
+    return 0;
+  }
+
+/* acknowledge control transfer */
+  void usb_pdi_ack_setup( usb_device_t *udev) {
+    pdiWriteEndpoint( PDI_EP0_TX, 0, 0);
+  }
+
+
+/* acknowledge control transfer */
+  void usb_pdi_ack_control_setup( usb_device_t *udev) {
+    pdiAckSetupControl();
+  }
+
+  
+/**
+ * usb_pdi_check events
+ * function reads interrupt register and sets event flags
+ * function returns 1 if there is some new event.
+ * function returns 0 if there isn't new event but all is OK
+ * function returns -1 if there is any error
+*/
+  int usb_pdi_check_events( usb_device_t *udev) {
+    volatile unsigned char LastTrans = 0;
+    volatile unsigned int LastInt;
+    int ret = 0, i;
+
+    LastInt = pdiGetInterrupt();
+if ( LastInt) {
+  usb_debug_print( DEBUG_LEVEL_LOW, ("PI=0x%04X\n", LastInt));
+}
+    usb_debug_print( DEBUG_LEVEL_HIGH, ("PDI Int=0x%04X\n", LastInt));
+    
+    if ( LastInt & PDI_INT_BUSRESET) {                 // D12 - Bus reset reached
+      pdiInitChipState();
+      udev->flags |= USB_FLAG_BUS_RESET;
+      ret = 1;
+    } else {
+      #ifdef PDIUSBD12
+      if ( LastInt & PDI_INT_SUSPEND) {                 // D12 - Suspend flag changed
+        udev->flags |= USB_FLAG_SUSPEND;
+        ret = 1;
+      }
+      #endif
+
+            
+      if ( LastInt & PDI_INT_EP0_OUT) {                // D12 - Ep0RxDone - some data was received in EP0
+        LastTrans = pdiGetLastTransStatus( PDI_EP0_RX);
+        if ( LastTrans & PDI_LTSTAT_SETUP) { // setup packet
+          udev->flags |= USB_FLAG_SETUP;
+        } else {
+          udev->flags |= USB_FLAG_EVENT_RX0;
+        }
+        ret = 1;
+      }      
+      if ( LastInt & PDI_INT_EP0_IN) {                 // D12 - Ep0TxDone - data in EP0 was sended
+        LastTrans = pdiGetLastTransStatus( PDI_EP0_TX);
+        udev->flags |= USB_FLAG_EVENT_TX0;
+        ret = 1;
+      }
+
+      
+      for( i=0; i<udev->cntep; i++) {
+        if ( LastInt & (udev->ep+i)->event_mask) {
+          LastTrans = pdiGetLastTransStatus( (udev->ep+i)->epnum);
+          udev->ep_events |= 1<<i;
+          LastInt &= ~((udev->ep+i)->event_mask);
+          ret = 1;
+        }
+      }
+
+      /* check unsupported endpoints */
+      if ( LastInt & PDI_INT_EP1_OUT) {                // D12 - Ep1RxDone - some data was received in EP1
+        LastTrans = pdiGetLastTransStatus( PDI_EP1_RX);
+        pdiSetEpStatus( PDI_EP1_RX, PDI_SET_EP_STALLED);
+      }
+      if ( LastInt & PDI_INT_EP1_IN) {                 // D12 - Ep1TxDone - data in EP1 was sended
+        LastTrans = pdiGetLastTransStatus( PDI_EP1_TX);
+        pdiSetEpStatus( PDI_EP1_TX, PDI_SET_EP_STALLED);
+      }
+      if ( LastInt & PDI_INT_EP2_OUT) {                // D12 - Ep2RxDone - some data was received in EP2
+        LastTrans = pdiGetLastTransStatus( PDI_EP2_RX);
+        pdiSetEpStatus( PDI_EP2_RX, PDI_SET_EP_STALLED);
+      }
+      if ( LastInt & PDI_INT_EP2_IN) {                 // D12 - Ep2TxDone - data in EP2 was sended
+        LastTrans = pdiGetLastTransStatus( PDI_EP2_TX);
+        pdiSetEpStatus( PDI_EP2_TX, PDI_SET_EP_STALLED);
+      }
+     #if defined(PDIUSBD11) || defined(PDIUSBH11A_SINGLE)  // D11,H11_S
+      if ( LastInt & PDI_INT_EP3_OUT) {                // D11 - Ep3RxDone - some data was received in EP3
+        LastTrans = pdiGetLastTransStatus( PDI_EP3_RX);
+        pdiSetEpStatus( PDI_EP3_RX, PDI_SET_EP_STALLED);
+      }    
+      if ( LastInt & PDI_INT_EP3_IN) {                 // D11 - Ep3TxDone - data in EP3 was sended
+        LastTrans = pdiGetLastTransStatus( PDI_EP3_TX);
+        pdiSetEpStatus( PDI_EP3_TX, PDI_SET_EP_STALLED);
+      }
+     #endif /* D11,H11_S */
+    }
+    return ret;
+  }
+
+
+/* stall endpoint X */
+  void usb_pdi_stall( usb_ep_t *ep) {
+    if ( ep->epnum) {
+      pdiSetEpStatus( ep->epnum, PDI_SET_EP_STALLED);
+    } else { // endpoint0
+      pdiSetEpStatus( PDI_EP0_TX, PDI_SET_EP_STALLED);
+      pdiSetEpStatus( PDI_EP0_RX, PDI_SET_EP_STALLED);    
+    }
+  }
+
+  int usb_pdi_read_endpoint( usb_ep_t *ep, void *ptr, int size) USB_UDEV_REENTRANT_SIGN
+  {
+    if(!ep->epnum)
+       return pdiReadEndpoint( PDI_EP0_RX, size, ptr);
+    else
+       return pdiReadEndpoint( ep->epnum, size, ptr);
+  }
+  int usb_pdi_write_endpoint( usb_ep_t *ep, const void *ptr, int size) USB_UDEV_REENTRANT_SIGN
+  {
+    if(!ep->epnum)
+       pdiWriteEndpoint( PDI_EP0_TX, size, ptr);
+    else
+       pdiWriteEndpoint( ep->epnum, size, ptr);
+    return size;
+  }
+
+    
+/* init usb structures and chip */
+  int usb_pdi_init( usb_device_t *udev) {
+
+   #ifndef USB_PDI_DIRECT_FNC
+    udev->connect = usb_pdi_connect;
+    udev->disconnect = usb_pdi_disconnect;
+    udev->ack_setup = usb_pdi_ack_setup;
+    udev->ack_control_setup = usb_pdi_ack_control_setup;
+    udev->stall = usb_pdi_stall;
+    udev->check_events = usb_pdi_check_events;
+    udev->read_endpoint = usb_pdi_read_endpoint;
+    udev->write_endpoint = usb_pdi_write_endpoint;
+   #endif /*USB_PDI_DIRECT_FNC*/
+
+    udev->ep0.max_packet_size = PDI_EP0_PACKET_SIZE;
+
+    pdiInitChipState();
+    pdiSetMode( PDI_MODE_BASE_VALUE);
+    return 0;
+  }
diff --git a/embedded/libs4c/usb/pdiusb/pdiusb.c b/embedded/libs4c/usb/pdiusb/pdiusb.c
new file mode 100644 (file)
index 0000000..280717c
--- /dev/null
@@ -0,0 +1,527 @@
+/*********************************************************/
+/***   Module : PDIUSB D11,H11,H11A,D12 - implement.   ***/
+/***   Author : Roman Bartosinski (C) 03.10.2002       ***/
+/***   Description : Integrate common functions for    ***/
+/***                PDIUSBD11,PDIUSBD12,PDIUSBH11(old) ***/
+/***                PDIUSBH11A in Single/Multiple mode ***/
+/***                 to one common file.               ***/
+/***   Modify : 10.10.2002 - add H11                   ***/
+/***            13.10.2002 - add spec.fnc for 'using'  ***/
+/*********************************************************/
+
+#include <system_def.h>
+#include <endian.h>
+#if __BYTE_ORDER == __BIG_ENDIAN
+  #include <byteswap.h>
+#endif
+#include <usb/pdiusb.h>
+#include <usb/usb_spec.h>
+
+  #ifdef PDI_CMD_RWD_INTERNAL
+   #ifndef PDIUSBD12
+     #include <periph/i2c.h>
+   #endif
+  #endif
+
+  #ifndef SDCC
+   #define xdata 
+  #endif
+
+
+/*********************************************************/
+// Function for read and write from/into chip
+
+ #if defined(PDI_CMD_RWD_INTERNAL)
+  #if defined(PDIUSBD12) // parallel interface
+
+   void pdiSendCommand( unsigned char byCmd) {
+     *((volatile xdata unsigned char *) PDIUSB_COMMAND_ADDR) = byCmd;
+   }
+   unsigned char pdiReadData( unsigned char byCount, void *pbyData) {
+     unsigned char out = byCount;
+     while (byCount) {
+       byCount--;
+       *(unsigned char*)pbyData++ = *((volatile xdata unsigned char *) PDIUSB_READ_DATA_ADDR);
+     }
+     return out;
+   }
+   void pdiWriteData( unsigned char byCount, const void *pbyData) {
+     while (byCount) {
+       byCount--;
+       *((volatile xdata unsigned char *) PDIUSB_WRITE_DATA_ADDR) = *(unsigned char*)pbyData++;
+     }
+   }
+
+   #if defined(PDI_USE_USING)
+     unsigned short pdiIntCmdReadData( unsigned char byCmd, unsigned char byShort) _PDI_USING {
+       unsigned char i[2];
+       *((volatile xdata unsigned char *) PDIUSB_COMMAND_ADDR) = byCmd;
+       i[0] = *((volatile xdata unsigned char *) PDIUSB_READ_DATA_ADDR);
+       if ( !byShort) {
+        i[1] = 0;
+        return i[0];
+       }
+       i[1] = *((volatile xdata unsigned char *) PDIUSB_READ_DATA_ADDR);
+       return (((unsigned short) i[1]) << 8) + i[0];
+     }
+   #endif
+
+  #else // serial interface iic
+   #ifndef D11_REG_CMD
+     #define D11_REG_CMD  PDIUSB_COMMAND_ADDR
+   #endif
+   #ifndef D11_REG_DATA_WRITE
+     #define D11_REG_DATA_WRITE PDIUSB_WRITE_DATA_ADDR
+   #endif
+   #ifndef D11_REG_DATA_READ
+     #define D11_REG_DATA_READ PDIUSB_READ_DATA_ADDR
+   #endif
+     
+   void pdiSendCommand( unsigned char byCmd) {
+     I2C_Write( D11_REG_CMD, &byCmd, 1);
+   }
+   unsigned char pdiReadData( unsigned char byCount, void *pbyData) {
+     I2C_Read( D11_REG_DATA_READ, pbyData, byCount);
+     return byCount;
+   }
+   void pdiWriteData( unsigned char byCount, const void *pbyData) {
+     I2C_Write( D11_REG_DATA_WRITE, pbyData, byCount);
+   }
+   #if defined(PDI_USE_USING)
+    unsigned short pdiIntCmdReadData( unsigned char byCmd, unsigned char byShort) _PDI_USING {
+    }
+   #endif
+
+  #endif
+ #endif
+
+
+/*********************************************************/
+/*********************************************************/
+// PDIUSB common commands
+
+#if defined(PDIUSBH11) || defined(PDIUSBH11A) || defined(PDIUSBD11)
+
+ /*********************************************************/
+ // pdiSetHUBAddressEnable
+ // enable HUB function and set address (byAddress is 0-0x7F, byEnable is 0 or 1)
+   void pdiSetHUBAddressEnable( unsigned char byAddress, unsigned char byEnable) {
+// usb_debug_print( DEBUG_LEVEL_HIGH, ("H "));
+     byAddress = (byAddress & 0x7F) | (byEnable << 7);
+     pdiSendCommand( PDI_CMD_HUB_ENB_ADDR);
+     pdiWriteData( 1, &byAddress);
+   }
+
+#endif
+#if !defined(PDIUSBH11A_MULTPLE) // D11,D12,H11,H11A_S(emb.fnc)
+
+ /*********************************************************/
+ // pdiSetAddressEnable
+ // Enable function and set address (byAddress is 0-0x7F, byEnable is 0 or 1)
+   void pdiSetAddressEnable( unsigned char byAddr_Enb) {
+// usb_debug_print( DEBUG_LEVEL_HIGH, ("A "));
+     pdiSendCommand( PDI_CMD_FNC_ENB_ADDR);
+     pdiWriteData( 1, &byAddr_Enb);
+   }
+
+#else
+
+ /*********************************************************/
+ // pdiSetEmbFncAddressEnable
+ // Enable Embedded function and set address (byAddress is 0-0x7F, byEnable is 0 or 1)
+ // byFnc - function index (zero based) 0-3
+   void pdiSetEmbFncAddressEnable( unsigned char byFnc, unsigned char byAddress, unsigned char byEnable) {
+     byAddress = (byAddress & 0x7F) | (byEnable << 7);
+     pdiSendCommand( PDI_CMD_FNC1_ENB_ADDR + byFnc);
+     pdiWriteData( 1, &byAddress);
+   }
+
+#endif
+
+
+
+ /*********************************************************/
+ // pdiSetEndpointEnable
+ // enable/disable endpoints (PDI_EPEN_xxx)
+   void pdiSetEndpointEnable( unsigned char byEnable) {
+// usb_debug_print( DEBUG_LEVEL_HIGH, ("E "));
+     pdiSendCommand( PDI_CMD_EPEN);
+     pdiWriteData( 1, &byEnable);
+   }
+
+
+#if !defined(PDIUSBH11)  // H11 has not it
+
+ /*********************************************************/
+ // pdiSetMode
+ // set chip mode (PDI_MODE_xxx) and clock division factor (PDI_CLOCK_xxx)
+  void pdiSetMode( unsigned short wMode_Clock) {
+     unsigned char sm[2];
+// usb_debug_print( DEBUG_LEVEL_HIGH, ("M%04X ",wMode_Clock));
+     sm[0] = (unsigned char) (wMode_Clock & 0xff);
+     sm[1] = (unsigned char) (wMode_Clock >> 8);
+     pdiSendCommand( PDI_CMD_SET_MODE);
+     pdiWriteData( 2, sm);
+   }
+
+#endif
+
+ #if defined(PDIUSBD12)
+
+ /*********************************************************/
+ // pdiSetDMA
+ // set DMA mode (PDI_DMA_xxx)
+  void pdiSetDMA( unsigned char byDma) {
+    pdiSendCommand( PDI_CMD_SET_DMA);
+    pdiWriteData( 1, &byDma);
+  }
+
+ /*********************************************************/
+ // pdiGetDMA
+ // get current DMA mode
+  unsigned char pdiGetDMA( void) {
+    unsigned char dma;
+    pdiSendCommand( PDI_CMD_GET_DMA);
+    pdiReadData( 1, &dma);
+    return dma;
+  }
+
+ #endif
+
+
+ #if defined(PDIUSBH11)
+
+ /*********************************************************/
+
+ // pdiGetInterrupt - H11 return only one byte
+ // get interrupt register (PDI_INT_xxx)
+  unsigned char pdiGetInterrupt( void) _PDI_USING {
+    unsigned char gin;
+#if defined(PDI_USE_USING)
+    return pdiIntCmdReadData( PDI_CMD_GET_INT_REG, 0);
+#else
+    pdiSendCommand( PDI_CMD_GET_INT_REG);
+    pdiReadData( 1, &gin);
+    return gin;
+#endif
+  }
+
+ #else
+
+ /*********************************************************/
+ // pdiGetInterrupt
+ // get interrupt register (PDI_INT_xxx)
+  unsigned short pdiGetInterrupt( void) _PDI_USING {
+    unsigned short gin;
+#if defined(PDI_USE_USING)
+    return pdiIntCmdReadData( PDI_CMD_GET_INT_REG, 1);
+#else
+    pdiSendCommand( PDI_CMD_GET_INT_REG);
+    pdiReadData( 2, &gin);
+   #if __BYTE_ORDER == __BIG_ENDIAN
+    gin=bswap_16(gin);
+   #endif
+    return gin; //pdiData[0] + (((unsigned short)pdiData[1])<<8);
+#endif
+  }
+
+ #endif
+
+ /*********************************************************/
+ // pdiSelectEp
+ // set internal buffer pointer to selected endpoint (zero based) (PDI_SELEP_xxx)
+  unsigned char pdiSelectEp( unsigned char byEpIdx) {
+    unsigned char sep;
+// usb_debug_print( DEBUG_LEVEL_HIGH, ("e%1d ",byEpIdx));
+    pdiSendCommand( PDI_CMD_SELECT_EP + byEpIdx);
+    pdiReadData( 1, &sep);
+    return sep;
+  }
+
+ /*********************************************************/
+ // pdiGetLastTransStatus
+ // get Last transaction status (PDI_LTSTAT_xxx and PDI_ERR_xxx)
+  unsigned char pdiGetLastTransStatus( unsigned char byEpIdx) _PDI_USING {
+    unsigned char lts;
+// usb_debug_print( DEBUG_LEVEL_HIGH, ("L "));
+#if defined(PDI_USE_USING)
+    return pdiIntCmdReadData( PDI_CMD_GET_LAST_STAT + byEpIdx, 0);
+#else
+    pdiSendCommand( PDI_CMD_GET_LAST_STAT + byEpIdx);
+    pdiReadData( 1, &lts);
+    return lts;
+#endif
+  }
+
+
+ #if defined(PDIUSBD11) || defined(PDIUSBH11) || defined(PDIUSBH11A)
+
+ /*********************************************************/
+ // pdiGetEpStatus
+ // get Endpoint Status (PDI_EPSTAT_xxx)
+  unsigned char pdiGetEpStatus( unsigned char byEpIdx) {
+    unsigned char ges;
+// usb_debug_print( DEBUG_LEVEL_HIGH, ("G "));
+    pdiSendCommand( PDI_CMD_GET_EP_STAT + byEpIdx);
+    pdiReadData( 1, &ges);
+    return ges;
+  }
+
+ #endif
+
+ /*********************************************************/
+ // pdiReadFromEpBuffer - raw reading
+ // read data from selected internal chip buffer
+ // if byLength < length of buffer data, so we read only byLength data)
+  unsigned char pdiReadFromEpBuffer( unsigned char byLength, unsigned char *pToBuff) {
+    unsigned char rdep[2];
+// usb_debug_print( DEBUG_LEVEL_HIGH, ("R "));
+    pdiSendCommand( PDI_CMD_READ_BUFFER);
+    pdiReadData( 2, rdep);
+    if ( rdep[1]) { // there is some data
+      if ( byLength < rdep[1]) // we need less data then is received
+        rdep[1] = byLength;
+      pdiReadData( rdep[1], pToBuff);
+    }
+    return rdep[1];
+  }
+
+ /*********************************************************/
+ // pdiWriteToEpBuffer - raw writing
+ // write data to selected internal chip buffer
+  void pdiWriteToEpBuffer( unsigned char byLength, const unsigned char *pFromBuff) {
+    unsigned char hd[2];
+// usb_debug_print( DEBUG_LEVEL_HIGH, ("W "));
+    pdiSendCommand( PDI_CMD_WRITE_BUFFER);
+    hd[0] = 0; hd[1] = byLength;
+    pdiWriteData( 2, hd);
+    if ( byLength) {
+      pdiWriteData( byLength, pFromBuff);
+    }
+  }
+
+ /*********************************************************/
+ // pdiSetEpStatus
+ // set endpoint stall flag
+  void pdiSetEpStatus( unsigned char byEpIdx, unsigned char byStatus) {
+// usb_debug_print( DEBUG_LEVEL_HIGH, ("T "));
+    pdiSendCommand( PDI_CMD_SET_EP_STAT + byEpIdx);
+    pdiWriteData( 1, &byStatus);
+  }
+
+ /*********************************************************/
+ // pdiAcknowledgeSetup
+ // chip disable fncs Validate and Clear after SETUP packet,
+ // this cmd re-enable these fncs
+  void pdiAcknowledgeSetup( void) {
+// usb_debug_print( DEBUG_LEVEL_HIGH, ("C "));
+    pdiSendCommand( PDI_CMD_ACK_SETUP);
+  }
+
+ /*********************************************************/
+ // pdiClearBuffer
+ // set endpoint flag 'empty' and next data can be receive
+  void pdiClearBuffer( void) {
+// usb_debug_print( DEBUG_LEVEL_HIGH, ("B "));
+    pdiSendCommand( PDI_CMD_CLEAR_BUFFER);
+  }
+
+
+ /*********************************************************/
+ // pdiValidateBuffer
+ // set endpoint flag 'full' and data can be send
+  void pdiValidateBuffer( void) {
+// usb_debug_print( DEBUG_LEVEL_HIGH, ("V "));
+    pdiSendCommand( PDI_CMD_VALID_BUFFER);
+  }
+
+ /*********************************************************/
+ // pdiSendResume
+ // send an upstream resume signal for 10ms
+  void pdiSendResume( void) {
+// usb_debug_print( DEBUG_LEVEL_HIGH, ("M "));
+    pdiSendCommand( PDI_CMD_SEND_RESUME);
+  }
+
+ /*********************************************************/
+ // pdiGetFrameNumber
+ // return frame number of last successfully received SOF
+  unsigned short pdiGetFrameNumber( void) {
+    unsigned short gfn;
+    pdiSendCommand( PDI_CMD_GET_FRAME);
+    pdiReadData( 2, &gfn);
+   #if __BYTE_ORDER == __BIG_ENDIAN
+    gfn=bswap_16(gfn);
+   #endif
+    return gfn; //pdiData[0] + (((unsigned short)pdiData[1])<<8);
+  }
+  
+ /*********************************************************/
+ // pdiGetChipID  - this function is undocumented
+ // read chip ID (not documented function) ( LSB is maybe type of chip in hex (0x12,0x11))
+  unsigned short pdiGetChipID( void) {
+    unsigned short gid;
+    pdiSendCommand( PDI_CMD_GET_CHIP_ID);
+    pdiReadData( 2, &gid);
+   #if __BYTE_ORDER == __BIG_ENDIAN
+    gid=bswap_16(gid);
+   #endif
+    return gid; //pdiData[0] + (((unsigned short)pdiData[1])<<8);
+  }    
+
+
+ /*********************************************************/
+ /*********************************************************/
+ // HUB command
+#if defined(PDIUSBH11) || defined(PDIUSBH11A)
+ /*********************************************************/
+ // pdiClearPortFeature
+ // clear feature 'byFeature' in downstream port 2-5 'byEpIdx' (zero based)
+  void pdiClearPortFeature( unsigned char byEpIdx, unsigned char byFeature) {
+    pdiSendCommand( PDI_CMD_P2_CLR_FEATURE + byEpIdx);
+    pdiWriteData( 1, &byFeature);
+  }
+
+ /*********************************************************/
+ // pdiSetPortFeature
+ // set feature 'byFeature' in downstream port 2-5 'byEpIdx' (zero based)
+  void pdiSetPortFeature( unsigned char byEpIdx, unsigned char byFeature) {
+    pdiSendCommand( PDI_CMD_P2_SET_FEATURE + byEpIdx);
+    pdiWriteData( 1, &byFeature);
+  }
+  
+ /*********************************************************/
+ // pdiGetPortFeature
+ // get port status (port status byte and port status change byte)
+  unsigned short pdiGetPortFeature( unsigned char byEpIdx) {
+    unsigned short gpf;
+    pdiSendCommand( PDI_CMD_P2_GET_STATUS + byEpIdx);
+    pdiReadData( 2, &gpf);
+   #if __BYTE_ORDER == __BIG_ENDIAN
+    gpf=bswap_16(gpf);
+   #endif
+    return gpf; //pdiData[0] + (((unsigned short)pdiData[1])<<8);
+  }
+  
+ /*********************************************************/
+ // pdiSetStatusChangeBits
+ // set local power change bits status
+  void pdiSetStatusChangeBits( unsigned char byBits) {
+    pdiSendCommand( PDI_CMD_SET_CHNG_BITS);
+    pdiWriteData( 1, &byBits);
+  }
+  
+#endif
+
+
+
+/*********************************************************/
+/*********************************************************/
+// PDIUSB other commands
+
+ // complex function for select endpoint, write data and validate data in endpoint buffer
+ void pdiWriteEndpoint( unsigned char byEpIdx, unsigned char byLength, const unsigned char *pbyData) {
+   pdiSelectEp( byEpIdx);
+   pdiWriteToEpBuffer( byLength, pbyData);
+   pdiValidateBuffer();
+ }
+
+ // complex function for select endpoint, read data and clear endpoint buffer
+ // byMaxLength means how many bytes will be maximally read.
+ unsigned char pdiReadEndpoint( unsigned char byEpIdx, unsigned char byMaxLength, unsigned char *pbyData) {
+   unsigned char cnt = 0, sep;
+   sep = pdiSelectEp( byEpIdx);
+   if ( sep & PDI_SELEP_FULL) {
+    cnt = pdiReadFromEpBuffer( byMaxLength, pbyData);
+    pdiClearBuffer();
+   }
+   return cnt;
+ }
+
+ // complex universal function for select command and read/write data to/from PDIUSB
+ unsigned char pdiCmdData( unsigned char byCmd, unsigned char *pbyData,
+                           unsigned char byCount, unsigned char byRead) {
+   pdiSendCommand( byCmd);
+   if ( byCount) {
+     if( byRead) byCount = pdiReadData( byCount, pbyData);  // Read Data
+     else pdiWriteData( byCount, pbyData);                  // Write Data
+   }
+   return byCount;   
+ }
+
+#if !defined(PDIUSBH11A_MULTIPLE)
+ // complex function for acknowledge control endpoint
+ void pdiAckSetupControl( void) {
+   pdiSendCommand( PDI_CMD_SELECT_EP + PDI_EP0_RX);
+   pdiSendCommand( PDI_CMD_ACK_SETUP);
+   pdiSendCommand( PDI_CMD_CLEAR_BUFFER);
+   pdiSendCommand( PDI_CMD_SELECT_EP + PDI_EP0_TX);
+   pdiSendCommand( PDI_CMD_ACK_SETUP);
+ }
+#else
+ // complex function for acknowledge control endpoint ( for one emb.fnc. 1,6,7) (zero-based 0,1,2)
+ void pdiAckSetupFncControl( unsigned char Fnc) {
+   unsigned char FncTab[3] = { PDI_F1_EP0_RX, PDI_F6_EP0_RX, PDI_F7_EP0_RX};
+   pdiSendCommand( PDI_CMD_SELECT_EP + FncTab[Fnc]);
+   pdiSendCommand( PDI_CMD_ACK_SETUP);
+   pdiSendCommand( PDI_CMD_CLEAR_BUFFER);
+   pdiSendCommand( PDI_CMD_SELECT_EP + FncTab[Fnc] + 1);
+   pdiSendCommand( PDI_CMD_ACK_SETUP);
+ }
+#endif
+
+#if defined(PDIUSBD12) // parallel interface
+ void pdiInit( void) {
+   pdiSetAddressEnable( PDI_ENAD_ENABLE);
+   pdiSetEndpointEnable( PDI_EPEN_ENABLE);
+   pdiSetDMA( PDI_DMA_EP4_INT | PDI_DMA_EP5_INT);
+   pdiSetMode( PDI_MODE_NO_LAZY_CLOCK | PDI_MODE_CLOCK_RUNNING |
+               PDI_MODE_SOFT_CONNECT | PDI_CLOCK_12M);
+ }
+#endif
+
+#if defined(PDIUSBH11A_SINGLE) // serial interface
+ void pdiInit( void) {
+   pdiSetHUBAddressEnable( 0, 0); // disable HUB
+   pdiSetAddressEnable( PDI_ENAD_ENABLE);    // enable emb.function
+   pdiSetEndpointEnable( PDI_EPEN_FNC_ENB);
+   pdiSetMode( PDI_MODE_REMOTE_WAKEUP | PDI_MODE_NO_LAZY_CLOCK | PDI_MODE_CLOCK_RUNNING |
+               PDI_MODE_SOFT_CONNECT | PDI_MODE_SINGLE_FNC | PDI_CLOCK_12M);
+ }
+#endif
+
+/*********************************************************/
+
+ static const unsigned char epin2idx[]={
+   PDI_EP0_IN,
+   PDI_EP1_IN,
+  #if PDI_CNT_EP > 1
+   PDI_EP2_IN,
+  #if PDI_CNT_EP > 2
+   PDI_EP3_IN,
+  #endif
+  #endif
+ };
+
+ static const unsigned char epout2idx[]={
+   PDI_EP0_OUT,
+   PDI_EP1_OUT,
+  #if PDI_CNT_EP > 1
+   PDI_EP2_OUT,
+  #if PDI_CNT_EP > 2
+   PDI_EP3_OUT,
+  #endif
+  #endif
+ };
+
+ // pdiEp2Idx
+ // convert endpoint number to pdi index number
+ unsigned char pdiEp2Idx(unsigned char ep) {
+   if(ep & USB_ENDPOINT_DIRECTION_MASK)
+     return epin2idx[ep & 0xf];
+   else
+     return epout2idx[ep & 0xf];
+ }
+
+ /*********************************************************/
+ /*********************************************************/
diff --git a/embedded/libs4c/usb/pdiusb/usb/pdi.h b/embedded/libs4c/usb/pdiusb/usb/pdi.h
new file mode 100644 (file)
index 0000000..21bb5db
--- /dev/null
@@ -0,0 +1,49 @@
+/*****************************************************/
+/***   Module : USB PDI - header file              ***/
+/***   Author : Roman Bartosinski (C) 28.04.2002   ***/
+/***   Modify : 08.08.2002, 16.04.2003             ***/
+/*****************************************************/
+
+#ifndef _USB_PDI_SUBMODULE_HEADER_FILE_
+  #define _USB_PDI_SUBMODULE_HEADER_FILE_
+
+  #include <usb/usb.h>
+//  int usb_pdi_init( usb_device_t *udev) REENTRANT_SIGN;
+  int usb_pdi_init( usb_device_t *udev);
+  
+  #ifdef USB_PDI_DIRECT_FNC
+    #define USB_PDI_EXPORT_FNC
+
+    #define usb_udev_is_fnc(_M_udev, _M_fnc) (1)
+
+    #define usb_udev_init usb_pdi_init
+    #define usb_udev_connect usb_pdi_connect
+    #define usb_udev_disconnect usb_pdi_disconnect
+    #define usb_udev_ack_setup usb_pdi_ack_setup
+    #define usb_udev_ack_control_setup usb_pdi_ack_control_setup
+    #define usb_udev_check_events usb_pdi_check_events
+
+    #define usb_udev_stall usb_pdi_stall
+    #define usb_udev_read_endpoint usb_pdi_read_endpoint
+    #define usb_udev_write_endpoint usb_pdi_write_endpoint
+
+  #endif /*USB_PDI_DIRECT_FNC*/
+
+  #ifdef USB_PDI_EXPORT_FNC
+
+    int usb_pdi_init( usb_device_t *udev);
+    int usb_pdi_connect( usb_device_t *udev);
+    int usb_pdi_disconnect( usb_device_t *udev);
+    void usb_pdi_ack_setup( usb_device_t *udev);
+    void usb_pdi_ack_control_setup( usb_device_t *udev);
+    int usb_pdi_check_events( usb_device_t *udev);
+
+    void usb_pdi_stall( usb_ep_t *ep);
+    int usb_pdi_read_endpoint( usb_ep_t *ep, void *ptr, int size) USB_UDEV_REENTRANT_SIGN;
+    int usb_pdi_write_endpoint( usb_ep_t *ep, const void *ptr, int size) USB_UDEV_REENTRANT_SIGN;
+
+  #endif /*USB_PDI_EXPORT_FNC*/
+
+#endif /* _USB_PDI_SUBMODULE_HEADER_FILE_ */
+
diff --git a/embedded/libs4c/usb/pdiusb/usb/pdiusb.h b/embedded/libs4c/usb/pdiusb/usb/pdiusb.h
new file mode 100644 (file)
index 0000000..14ce3ab
--- /dev/null
@@ -0,0 +1,674 @@
+/*********************************************************/
+/***   Module : PDIUSB D11,H11,H11A,D12 - header file  ***/
+/***   Author : Roman Bartosinski (C) 03.10.2002       ***/
+/***   Description : Integrate common functions for    ***/
+/***                PDIUSBD11,PDIUSBD12,PDIUSBH11(old) ***/
+/***                PDIUSBH11A in Single/Multiple mode ***/
+/***                 to one common file.               ***/
+/***   Modify : 10.10.2002 - add H11                   ***/
+/***            13.10.2002 - add spec.fnc for 'using'  ***/
+/***            22.12.2002 - rebuild for smaller out   ***/
+/*********************************************************/
+
+#ifndef _PDIUSB_BASE_MODULE
+ #define _PDIUSB_BASE_MODULE
+
+/*********************************************************/
+// Comments - !!! Please, read this section !!!
+//
+//
+// If you can use included functions for read and write
+//  byte from/to PDIUSB, please uncomment defined PDI_CMD_RWD_INTERNAL
+//  and check defined addresses for communication with PDIUSB.
+// Else you must uncomment defined PDI_CMD_RWD_EXTERNAL and declare
+//  and implement next functions :
+//     void pdiSendCommand( unsigned char byCmd);
+//     unsigned char pdiReadData( unsigned char byCount, void *pbyData);
+//     void pdiWriteData( unsigned char byCount, const void *pbyData);
+//  - if you want use 'using' (see below), you must implement next function(on i51 is NEEDED).
+//     unsigned short pdiIntCmdReadData( unsigned char byCmd, unsigned char byShort) _PDI_USING;
+// -- all in section 'External functions'
+//
+//
+// Next you must select type of chip.(uncomment line with defined type)
+// -- in section 'Type of PDIUSB'
+//
+//
+// If you want use functions 'pdiGetInterrupt' and 'pdiGetLastTransStatus'
+// with keyword 'using' (for i51 it means using spec.reg.bank), uncomment
+// define 'USING'. Only these two functions need pdiIntCmdReadData.
+// -- in section 'Use using in interrupt functions'
+//
+// ***   External choice   ***
+// Or you can make all previous choises externally before including this file
+// by defining one of PDIUSBD11,PDIUSBD12,PDIUSBH11,PDIUSBH11A_SINGLE,PDIUSBH11A_MULTIPLE
+//
+// defining one of PDI_CMD_RWD_INTERNAL,PDI_CMD_RWD_EXTERNAL
+// (you can define externally PDIUSB_COMMAND_ADDR, PDIUSB_READ_DATA_ADDR, PDIUSB_WRITE_DATA_ADDR)
+//
+// and defining one of PDI_USE_USING,PDI_DONTUSE_USING
+// (you can define externally _PDI_USING_NUMBER)
+
+
+
+/*********************************************************/ 
+// Type of PDIUSB
+
+
+//
+//   PDIUSBD11           - USB device with serial interface
+//   PDIUSBH11           - USB hub with one embedded fnc and serial interface
+//   PDIUSBH11A_SINGLE   - USB hub with one embedded fnc, serial interface and additional functions
+//   PDIUSBH11A_MULTIPLE - USB hub with multiple(3) embedded fncs, serial interface and add.fncs
+//   - H11A_SINGLE and H11A_MULTIPLE is divided by pdiusb command SetMode (bit is set automatically)
+//   PDIUSBD12           - USB device with parallel interface
+//
+
+// uncomment right chip type below
+
+#define PDIUSBD11
+//#define PDIUSBH11
+//#define PDIUSBH11A_SINGLE
+//#define PDIUSBH11A_MULTIPLE
+//#define PDIUSBD12
+
+                                                              
+/*********************************************************/
+// Create common type PDIUSBH11A for SINGLE and MULTIPLE
+// for mux H11A_S & H11A_M
+#if defined(PDIUSBH11A_SINGLE) || defined(PDIUSBH11A_MULTIPLE)
+  #define PDIUSBH11A
+#else
+  #undef  PDIUSBH11A
+#endif
+
+
+
+/*********************************************************/
+//  Use using in interrupt functions
+
+  // If you want use keyword 'using' in function
+  // 'pdiGetInterrupt' and 'pdiGetLastTransStatus',
+  // uncomment next line.(and check and correct number in _PDI_USING_NUMBER)
+//#define PDI_USE_USING
+  // If you don't want use keyword 'using',
+  // uncomment next line.
+#define PDI_DONTUSE_USING
+
+ #if defined(PDI_USE_USING)
+  #if !defined(_PDI_USING_NUMBER)
+   #define _PDI_USING_NUMBER  2
+  #endif
+  #define _PDI_USING   using _PDI_USING_NUMBER
+ #else
+  #define _PDI_USING
+ #endif
+
+
+/*********************************************************/
+//  External functions
+
+  // If you want use internal functions, uncomment next line.
+//#define PDI_CMD_RWD_INTERNAL
+  // If you want use your own external functions, uncomment next line.
+//#define PDI_CMD_RWD_EXTERNAL
+
+// this is automatically selected by your choice
+
+ #if defined(PDI_CMD_RWD_INTERNAL)
+  #if !defined(PDIUSB_COMMAND_ADDR)       // if not defined address for select command
+   #if defined(PDIUSBD12)
+    #define PDIUSB_COMMAND_ADDR    0x7001 // sel.cmd address for D12 (this is address for my application)
+   #else
+    #define PDIUSB_COMMAND_ADDR    0x36   // sel.cmd address for all other
+   #endif
+  #endif
+  #if !defined(PDIUSB_READ_DATA_ADDR)     // if not defined address for read data from chip
+   #if defined(PDIUSBD12)
+    #define PDIUSB_READ_DATA_ADDR  0x7000 // read data address for D12
+   #else
+    #define PDIUSB_READ_DATA_ADDR  0x35   // read data address for all other
+   #endif
+  #endif
+  #if !defined(PDIUSB_WRITE_DATA_ADDR)    // if not defined address for write data to chip
+   #if defined(PDIUSBD12)
+    #define PDIUSB_WRITE_DATA_ADDR 0x7000 // write data address for D12
+   #else
+    #define PDIUSB_WRITE_DATA_ADDR 0x34   // write data address for all other
+   #endif
+  #endif
+
+ #endif  
+
+/* Build internal version of functions, but do not define addresses */
+#define PDI_CMD_RWD_INTERNAL
+
+  extern void pdiSendCommand( unsigned char byCmd);
+  extern unsigned char pdiReadData( unsigned char byCount, void *pbyData);
+  extern void pdiWriteData( unsigned char byCount, const void *pbyData);
+#if defined(PDI_USE_USING)
+  extern unsigned short pdiIntCmdReadData( unsigned char byCmd, unsigned char byShort) _PDI_USING;
+#endif
+
+
+/*********************************************************/
+// Check chip selection, int/ext rw functions, using
+
+#if !defined(PDIUSBD11) && !defined(PDIUSBH11) && !defined(PDIUSBH11A) && !defined(PDIUSBD12)
+  #define _PDI_ERROR_NO_CONTINUE
+  #error "!!! Any type of PDIUSB wasn't selected !!!"
+  #error "Please select one of PDIUSB in file pdiusb.h in section 'Type of PDIUSB'."  
+#endif
+#if !defined(PDI_CMD_RWD_INTERNAL) && !defined(PDI_CMD_RWD_EXTERNAL)
+  #define _PDI_ERROR_NO_CONTINUE
+  #error "!!! You must select if you want use internal or external basic fncs for PDIUSB !!!"
+  #error "Please select your choice in file pdiusb.h in section 'External functions'."
+#endif
+#if !defined(PDI_USE_USING) && !defined(PDI_DONTUSE_USING)
+  #define _PDI_ERROR_NO_CONTINUE
+  #error "!!! You must choose if you want keyword 'using' !!!"
+  #error "Please see into file pdiusb.h in section 'Use using in interrupt functions'."
+#endif
+
+#if defined(_PDI_ERROR_NO_CONTINUE)
+  #error " For help ... read in file pdiusb.h section 'Comments'."
+#endif
+
+
+/*********************************************************/
+/*********************************************************/
+#if !defined(_PDI_ERROR_NO_CONTINUE)
+
+/*********************************************************/    
+// Endpoints - size and index defines
+
+  //  PDI_CNT_EP - number of endpoints without control endpoints
+#if defined(PDIUSBD11) || defined(PDIUSBH11A_SINGLE)       // D11, H11A_S
+  #define PDI_CNT_EP    0x03
+#elif defined(PDIUSBH11) || defined(PDIUSBH11A_MULTIPLE)  // H11, H11A_M
+  #define PDI_CNT_EP    0x01
+#elif defined(PDIUSBD12)                                  // D12
+  #define PDI_CNT_EP    0x02
+#endif
+
+  //  PDI_EPx_yyyy_SIZE - max packet size for endpoint x  
+#if defined(PDIUSBH11) || defined(PDIUSBH11A)             // H11, H11A
+  #define PDI_HUB_TX_SIZE      8
+  #define PDI_HUB_RX_SIZE      8
+  #define PDI_HUB_PACKET_SIZE  8
+ #if defined(PDIUSBH11)
+  #define PDI_HUB_INT_SIZE     1
+ #endif
+#endif
+
+
+#if !defined(PDIUSBD12)                     // D11,H11,H11A
+  #define PDI_EP0_TX_SIZE      8
+  #define PDI_EP0_RX_SIZE      8
+  #define PDI_EP0_PACKET_SIZE  8
+  #define PDI_EP1_TX_SIZE      8
+  #define PDI_EP1_RX_SIZE      8
+  #define PDI_EP1_PACKET_SIZE  8
+ #if defined(PDIUSBD11) || defined(PDIUSBH11A_SINGLE)
+  #define PDI_EP2_TX_SIZE      8
+  #define PDI_EP2_RX_SIZE      8
+  #define PDI_EP2_PACKET_SIZE  8
+  #define PDI_EP3_TX_SIZE      8
+  #define PDI_EP3_RX_SIZE      8
+  #define PDI_EP3_PACKET_SIZE  8
+ #endif
+#else                                       // D12
+  #define PDI_EP0_TX_SIZE      16
+  #define PDI_EP0_RX_SIZE      16
+  #define PDI_EP0_PACKET_SIZE  16
+  #define PDI_EP1_TX_SIZE      16
+  #define PDI_EP1_RX_SIZE      16
+  #define PDI_EP1_PACKET_SIZE  16
+  #define PDI_EP2_TX_SIZE      64
+  #define PDI_EP2_RX_SIZE      64
+  #define PDI_EP2_PACKET_SIZE  64
+#endif
+
+  //  PDI_EPx_TX, PDI_EPx_RX - index for endpoint x (write/read)
+#if defined(PDIUSBH11) || defined(PDIUSBH11A)                                        // H11
+  #define PDI_HUB_EP0_RX  0
+  #define PDI_HUB_EP0_TX  1
+  // another index names
+  #define PDI_HUB_EP0_OUT  PDI_HUB_EP0_RX
+  #define PDI_HUB_EP0_IN   PDI_HUB_EP0_TX
+#endif
+
+#if defined(PDIUSBH11)
+  #define PDI_EP0_RX  2
+  #define PDI_EP0_TX  3
+  #define PDI_EP1_TX  4
+  // another index names
+  #define PDI_EP0_OUT  PDI_EP0_RX
+  #define PDI_EP0_IN   PDI_EP0_TX
+  #define PDI_EP1_IN   PDI_EP1_TX
+#elif defined(PDIUSBD11) || defined(PDIUSBH11A_SINGLE)          // D11,H11A_S
+  #define PDI_EP0_RX  2
+  #define PDI_EP0_TX  3
+  #define PDI_EP1_RX  5
+  #define PDI_EP1_TX  4
+  #define PDI_EP2_RX  6
+  #define PDI_EP2_TX  7
+  #define PDI_EP3_RX  8
+  #define PDI_EP3_TX  9
+  // another index names
+  #define PDI_EP0_OUT  PDI_EP0_RX
+  #define PDI_EP0_IN   PDI_EP0_TX
+  #define PDI_EP1_OUT  PDI_EP1_RX
+  #define PDI_EP1_IN   PDI_EP1_TX
+  #define PDI_EP2_OUT  PDI_EP2_RX
+  #define PDI_EP2_IN   PDI_EP2_TX
+  #define PDI_EP3_OUT  PDI_EP3_RX
+  #define PDI_EP3_IN   PDI_EP3_TX
+#elif defined(PDIUSBH11A_MULTIPLE)                            // H11_M
+  #define PDI_F1_EP0_RX   2
+  #define PDI_F1_EP0_TX   3
+  #define PDI_F1_EP1_RX   5
+  #define PDI_F1_EP1_TX   4
+  #define PDI_F6_EP0_RX  10
+  #define PDI_F6_EP0_TX  11
+  #define PDI_F6_EP1_RX   6
+  #define PDI_F6_EP1_TX   7
+  #define PDI_F7_EP0_RX  12
+  #define PDI_F7_EP0_TX  13
+  #define PDI_F7_EP1_RX   8
+  #define PDI_F7_EP1_TX   9
+  // another index names
+  #define PDI_F1_EP0_OUT  PDI_F1_EP0_RX
+  #define PDI_F1_EP0_IN   PDI_F1_EP0_TX
+  #define PDI_F1_EP1_OUT  PDI_F1_EP1_RX
+  #define PDI_F1_EP1_IN   PDI_F1_EP1_TX
+  #define PDI_F6_EP0_OUT  PDI_F6_EP0_RX
+  #define PDI_F6_EP0_IN   PDI_F6_EP0_TX
+  #define PDI_F6_EP1_OUT  PDI_F6_EP1_RX
+  #define PDI_F6_EP1_IN   PDI_F6_EP1_TX
+  #define PDI_F7_EP0_OUT  PDI_F7_EP0_RX
+  #define PDI_F7_EP0_IN   PDI_F7_EP0_TX
+  #define PDI_F7_EP1_OUT  PDI_F7_EP1_RX
+  #define PDI_F7_EP1_IN   PDI_F7_EP1_TX
+#elif defined(PDIUSBD12)                                     // D12
+  #define PDI_EP0_RX  0
+  #define PDI_EP0_TX  1
+  #define PDI_EP1_RX  2
+  #define PDI_EP1_TX  3
+  #define PDI_EP2_RX  4
+  #define PDI_EP2_TX  5
+  // another index names
+  #define PDI_EP0_OUT  PDI_EP0_RX
+  #define PDI_EP0_IN   PDI_EP0_TX
+  #define PDI_EP1_OUT  PDI_EP1_RX
+  #define PDI_EP1_IN   PDI_EP1_TX
+  #define PDI_EP2_OUT  PDI_EP2_RX
+  #define PDI_EP2_IN   PDI_EP2_TX
+#endif
+
+/*********************************************************/
+//  Commands - index and bits, description
+
+  // Set Address/Enable
+#if defined(PDIUSBH11) || defined(PDIUSBH11A) || defined(PDIUSBD11)         // only H11 or H11A
+  #define PDI_CMD_HUB_ENB_ADDR  0x00D0
+ #if defined(PDIUSBH11) || defined(PDIUSBH11A_SINGLE)  // for H11 and H11A_SINGLE
+  #define PDI_CMD_FNC_ENB_ADDR  0x00D1
+ #else                                                 // for H11A_MULTIPLE
+  #define PDI_CMD_FNC1_ENB_ADDR 0x00D1
+  #define PDI_CMD_FNC6_ENB_ADDR 0x00D2
+  #define PDI_CMD_FNC7_ENB_ADDR 0x00D3
+// for compatible with H11A_SINGLE and other
+  #define PDI_CMD_FNC_ENB_ADDR  PDI_CMD_FNC1_ENB_ADDR
+ #endif
+#elif defined(PDIUSBD11)             // for D11
+  #define PDI_CMD_FNC_ENB_ADDR  0x00D1
+#elif defined(PDIUSBD12)             // for D12
+  #define PDI_CMD_FNC_ENB_ADDR  0x00D0
+#endif
+    // set address/enable bits - for all
+    #define PDI_ENAD_ENABLE   0x0080
+    #define PDI_ENAD_ADDRMASK 0x007F
+
+  // Set Endpoint enable
+  #define PDI_CMD_EPEN          0x00D8
+    // set endpoint enable bits
+   #if defined(PDIUSBD12)             // D12 - generic ep
+    #define PDI_EPEN_ENABLE       0x0001
+   #elif defined(PDIUSBD11)           // D11 - generic ep
+    #define PDI_EPEN_ENABLE       0x0002
+   #elif defined(PDIUSBH11A) || defined(PDIUSBH11)   // H11,H11A
+    #define PDI_EPEN_HUB_ENB      0x0001
+     #if defined(PDIUSBH11A_MULTIPLE)  // H11A_M
+    #define PDI_EPEN_FNC1_ENB       0x0002     
+    #define PDI_EPEN_FNC6_ENB       0x0004
+    #define PDI_EPEN_FNC7_ENB       0x0008
+     #else                            // H11,H11A_S
+    #define PDI_EPEN_FNC_ENB      0x0002
+     #endif 
+   #endif
+
+ #if !defined(PDIUSBH11)
+  // Set Mode
+  #define PDI_CMD_SET_MODE      0x00F3
+    // set mode bits - configuration
+   #if !defined(PDIUSBD12)
+    #define PDI_MODE_REMOTE_WAKEUP   0x0001  // D11,H11A
+   #endif
+    #define PDI_MODE_NO_LAZY_CLOCK   0x0002  // all
+    #define PDI_MODE_CLOCK_RUNNING   0x0004  // all
+   #if defined(PDIUSBD12)
+    #define PDI_MODE_INTERRUPT_MODE  0x0008  // D12
+   #else
+    #define PDI_MODE_DEBUG_MODE      0x0008  // D11,H11A
+   #endif
+    #define PDI_MODE_SOFT_CONNECT    0x0010  // all
+   #if defined(PDIUSBH11A)
+    #define PDI_MODE_DWN_RESISTORS   0x0020  // H11A
+    #define PDI_MODE_NONBLINK_LED    0x0040  // H11A
+    #define PDI_MODE_SINGLE_FNC      0x0080  // H11A
+   #elif defined(PDIUSBD11)
+    #define PDI_MODE_MUSTBEONE       0x0080  // D11
+   #else
+    #define PDI_MODE_EP_NONISO       0x0000  // D12
+    #define PDI_MODE_EP_ISOOUT       0x0040
+    #define PDI_MODE_EP_ISOIN        0x0080
+    #define PDI_MODE_EP_ISOIO        0x00C0
+
+   #endif
+   // set mode bits - clock div factor  [48Mhz/(N+1)]
+   #if defined(PDIUSBH11A)
+    #define PDI_CLOCK_CRYSTAL_12M    0x3000  // for 12Mhz crystal
+    #define PDI_CLOCK_CRYSTAL_48M    0x0000  // for 48Mhz crystal
+   #endif
+   #if defined(PDIUSBD12)                  // D12
+    #define PDI_CLOCK_48M            0x0000    // 48 Mhz
+   #endif                                  // all
+    #define PDI_CLOCK_24M            0x0100    // 24 Mhz
+    #define PDI_CLOCK_16M            0x0200    // 16 Mhz
+    #define PDI_CLOCK_12M            0x0300    // 12 Mhz    
+    #define PDI_CLOCK_9M6            0x0400    //  9.6 Mhz
+    #define PDI_CLOCK_8M             0x0500    //  8 Mhz
+    #define PDI_CLOCK_6M8            0x0600    //  6.857142857 Mhz
+    #define PDI_CLOCK_6M             0x0700    //  6 Mhz
+    #define PDI_CLOCK_5M3            0x0800    //  5.333333333 Mhz
+    #define PDI_CLOCK_4M8            0x0900    //  4.8 Mhz
+    #define PDI_CLOCK_4M3            0x0A00    //  4.363636364 Mhz
+    #define PDI_CLOCK_4M             0x0B00    //  4 Mhz
+   #if defined(PDIUSBD12)                  // D12
+    #define PDI_CLOCK_SET_TO_ONE     0x4000
+    #define PDI_CLOCK_SOF_ONLY       0x8000
+   #endif
+ #endif
+   
+  // Set DMA
+ #if defined(PDIUSBD12)
+  #define PDI_CMD_SET_DMA       0x00FB
+  #define PDI_CMD_GET_DMA       0x00FB
+    // set dma bits
+    #define PDI_DMA_SINGLE_DMA    0x0000
+    #define PDI_DMA_BURST_4       0x0001
+    #define PDI_DMA_BURST_8       0x0002
+    #define PDI_DMA_BURST_16      0x0003
+    #define PDI_DMA_ENABLE        0x0004
+    #define PDI_DMA_DIRECTION     0x0008
+    #define PDI_DMA_AUTOLOAD      0x0010
+    #define PDI_DMA_INT_SOF       0x0020
+    #define PDI_DMA_EP4_INT       0x0040
+    #define PDI_DMA_EP5_INT       0x0080
+ #endif
+
+  // Read Interrupt Register
+  // be careful with PDIUSBH11 - you must read only 1 byte
+  #define PDI_CMD_GET_INT_REG   0x00F4
+    // read interrupt register bits
+   #if defined(PDIUSBD11) || defined(PDIUSBH11) || defined(PDIUSBH11A) // D11,H11,H11A
+     #if defined(PDIUSBH11) || defined(PDIUSBH11A)
+    #define PDI_INT_HUB_OUT       0x0001
+    #define PDI_INT_HUB_IN        0x0002
+     #endif
+     #if defined(PDIUSBH11)
+    #define PDI_INT_EP0_OUT       0x0004
+    #define PDI_INT_EP0_IN        0x0008
+    #define PDI_INT_EP1_IN        0x0010
+     #elif defined(PDIUSBD11) || defined(PDIUSBH11A_SINGLE)  // D11,H11_S
+    #define PDI_INT_EP0_OUT       0x0004
+    #define PDI_INT_EP0_IN        0x0008
+    #define PDI_INT_EP1_OUT       0x0020
+    #define PDI_INT_EP1_IN        0x0010
+    #define PDI_INT_EP2_OUT       0x0040
+    #define PDI_INT_EP2_IN        0x0080
+    #define PDI_INT_EP3_OUT       0x0100
+    #define PDI_INT_EP3_IN        0x0200
+     #else                                                // H11_M
+    #define PDI_INT_F1_EP0_OUT    0x0004
+    #define PDI_INT_F1_EP0_IN     0x0008
+    #define PDI_INT_F1_EP1_OUT    0x0020
+    #define PDI_INT_F1_EP1_IN     0x0010
+    #define PDI_INT_F6_EP0_OUT    0x0400
+    #define PDI_INT_F6_EP0_IN     0x0800
+
+    #define PDI_INT_F6_EP1_OUT    0x0040
+    #define PDI_INT_F6_EP1_IN     0x0080
+    #define PDI_INT_F7_EP0_OUT    0x1000
+    #define PDI_INT_F7_EP0_IN     0x2000
+    #define PDI_INT_F7_EP1_OUT    0x0100
+    #define PDI_INT_F7_EP1_IN     0x0200
+     #endif
+    #define PDI_INT_BUSRESET      0x4000
+   #elif defined(PDIUSBD12)
+    #define PDI_INT_EP0_OUT       0x0001
+    #define PDI_INT_EP0_IN        0x0002
+    #define PDI_INT_EP1_OUT       0x0004
+    #define PDI_INT_EP1_IN        0x0008
+    #define PDI_INT_EP2_OUT       0x0010
+    #define PDI_INT_EP2_IN        0x0020
+    #define PDI_INT_BUSRESET      0x0040
+    #define PDI_INT_SUSPEND       0x0080
+    #define PDI_INT_DMA_EOT       0x0100
+   #endif
+
+  // Select Endpoint
+  #define PDI_CMD_SELECT_EP     0x0000  // base index for select endpoint
+    // select endpoint bits
+    #define PDI_SELEP_FULL        0x0001
+   #if defined(PDIUSBD12)
+    #define PDI_SELEP_STALL       0x0002
+   #endif
+
+  // Read Last Transaction Status Register
+  #define PDI_CMD_GET_LAST_STAT 0x0040  // base index for read last transaction
+    // read last transaction bits and errors
+    #define PDI_LTSTAT_RXTX_OK    0x0001
+    #define PDI_LTSTAT_ERR_MASK   0x001E
+    #define PDI_LTSTAT_SETUP      0x0020
+    #define PDI_LTSTAT_DATA1      0x0040
+    #define PDI_LTSTAT_PREV_NRD   0x0080
+      // error codes
+      #define PDI_ERR_NO_ERROR      0x0000
+      #define PDI_ERR_PID_ENCODING  0x0001
+      #define PDI_ERR_PID_UNKNOWN   0x0002
+      #define PDI_ERR_UNEXPECT_PKT  0x0003
+
+      #define PDI_ERR_TOKEN_CRC     0x0004
+      #define PDI_ERR_DATA_CRC      0x0005
+      #define PDI_ERR_TIME_OUT      0x0006
+      #define PDI_ERR_NEVER_HAPPENS 0x0007
+      #define PDI_ERR_UNEXPECT_EOP  0x0008
+      #define PDI_ERR_NAK           0x0009
+      #define PDI_ERR_STALL         0x000A
+      #define PDI_ERR_OVERFLOW      0x000B
+      #define PDI_ERR_BITSTUFF      0x000D
+      #define PDI_ERR_DATA_PID      0x000F
+
+  // Read Endpoint Status
+ #if defined(PDIUSBD11) || defined(PDIUSBH11) || defined(PDIUSBH11A)
+   #define PDI_CMD_GET_EP_STAT   0x0080  // base index for read ep status
+    // read ep status bits
+     #define PDI_EPSTAT_SETUP      0x0004
+     #define PDI_EPSTAT_STALL      0x0008
+     #define PDI_EPSTAT_DATA1      0x0010
+     #define PDI_EPSTAT_FULL       0x0020
+ #endif
+
+  // Read Buffer
+  #define PDI_CMD_READ_BUFFER   0x00F0
+  
+  // Write Buffer
+  #define PDI_CMD_WRITE_BUFFER  0x00F0
+
+  // Clear Buffer
+  #define PDI_CMD_CLEAR_BUFFER  0x00F2
+
+  // Validate Buffer
+  #define PDI_CMD_VALID_BUFFER  0x00FA
+
+
+  // Set Endpoint Status
+  #define PDI_CMD_SET_EP_STAT   0x0040  // base index for endpoint status
+    // set endpoint status bits
+    #define PDI_SET_EP_STALLED    0x0001
+
+  // Acknowledge Setup
+  #define PDI_CMD_ACK_SETUP     0x00F1
+
+  // Send Resume
+  #define PDI_CMD_SEND_RESUME   0x00F6
+
+  // Read Current Frame Number
+  #define PDI_CMD_GET_FRAME     0x00F5
+
+  // Get Chip ID
+  #define PDI_CMD_GET_CHIP_ID   0x00FD
+
+// HUB commands
+#if defined(PDIUSBH11) || defined(PDIUSBH11A)
+  // Clear Port Feature
+  #define PDI_CMD_P2_CLR_FEATURE 0x00E0
+  #define PDI_CMD_P3_CLR_FEATURE 0x00E1
+  #define PDI_CMD_P4_CLR_FEATURE 0x00E2
+  #define PDI_CMD_P5_CLR_FEATURE 0x00E3
+  // Set Port Feature
+  #define PDI_CMD_P2_SET_FEATURE 0x00E8
+  #define PDI_CMD_P3_SET_FEATURE 0x00E9
+  #define PDI_CMD_P4_SET_FEATURE 0x00EA
+  #define PDI_CMD_P5_SET_FEATURE 0x00EB
+    // Feature code
+    #define PDI_F_PORT_ENABLE       0
+    #define PDI_F_PORT_SUSPEND      1
+    #define PDI_FC_PORT_RESET       2
+    #define PDI_F_PORT_POWER        3
+    #define PDI_C_PORT_CONNECTION   4
+    #define PDI_C_PORT_ENABLE       5
+    #define PDI_C_PORT_SUSPEND      6
+    #define PDI_C_PORT_OVERCURRENT  7
+   
+  // Get Port Status
+  #define PDI_CMD_P2_GET_STATUS  0x00E0
+  #define PDI_CMD_P3_GET_STATUS  0x00E1
+  #define PDI_CMD_P4_GET_STATUS  0x00E2
+  #define PDI_CMD_P5_GET_STATUS  0x00E3
+    // get port status bits - port status byte
+    #define PDI_PSTAT_CONNECT        0x0001
+    #define PDI_PSTAT_ENABLED        0x0002
+    #define PDI_PSTAT_SUSPEND        0x0004
+    #define PDI_PSTAT_OVERCUR        0x0008
+    #define PDI_PSTAT_RESET          0x0010
+    #define PDI_PSTAT_POWER          0x0020
+    #define PDI_PSTAT_LOWSPEED       0x0040
+    // get port status bits - port status change byte
+    #define PDI_PSTAT_CHANGE_CONNECT 0x0100
+    #define PDI_PSTAT_CHANGE_ENABLED 0x0200
+    #define PDI_PSTAT_CHANGE_SUSPEND 0x0400
+    #define PDI_PSTAT_CHANGE_OVERCUR 0x0800
+    #define PDI_PSTAT_CHANGE_RESET   0x1000
+  // Set Status Change Bits
+  #define PDI_CMD_SET_CHNG_BITS  0x00F7
+    // set status change bits - bits
+    #define PDI_SCHB_LOCAL_POWER    0x0001
+    #define PDI_SCHB_FNC1           0x0002
+   #if !defined(PDIUSBH11) && !defined(PDIUSBH11A_SINGLE)
+    #define PDI_SCHB_FNC6           0x0004
+    #define PDI_SCHB_FNC7           0x0008
+   #endif
+#endif
+
+
+/*********************************************************/
+//  Function prototypes
+//
+// PDIUSB common commands
+ #if defined(PDIUSBH11) || defined(PDIUSBH11A) || defined(PDIUSBD11)
+  void pdiSetHUBAddressEnable( unsigned char byAddress, unsigned char byEnable);
+ #endif
+ #if !defined(PDIUSBH11A_MULTIPLE) // D11,D12,H11,H11A_S(emb.fnc)
+  void pdiSetAddressEnable( unsigned char byAddr_Enb);
+//  void pdiSetAddressEnable( unsigned char byAddress, unsigned char byEnable);
+ #else
+  void pdiSetEmbFncAddressEnable( unsigned char byFnc, unsigned char byAddress, unsigned char byEnable);
+ #endif
+
+  void pdiSetEndpointEnable( unsigned char byEnable);
+  
+ #if !defined(PDIUSBH11)  // H11 has not it ( !!! is great - try give single quote mark into comments ;-)
+  void pdiSetMode( unsigned short wMode_Clock);
+ #endif
+ #if defined(PDIUSBD12)
+  void pdiSetDMA( unsigned char byDma);
+  unsigned char pdiGetDMA( void);
+ #endif
+
+ #if defined(PDIUSBH11)
+  unsigned char pdiGetInterrupt( void) _PDI_USING;
+ #else
+  unsigned short pdiGetInterrupt( void) _PDI_USING;
+ #endif
+  
+  unsigned char pdiSelectEp( unsigned char byEpIdx);
+  unsigned char pdiGetLastTransStatus( unsigned char byEpIdx) _PDI_USING;
+
+ #if defined(PDIUSBD11) || defined(PDIUSBH11) || defined(PDIUSBH11A)
+  unsigned char pdiGetEpStatus( unsigned char byEpIdx);
+ #endif
+
+  unsigned char pdiReadFromEpBuffer( unsigned char byLength, unsigned char *pToBuff);
+  void pdiWriteToEpBuffer( unsigned char byLength, const unsigned char *pFromBuff);
+  void pdiSetEpStatus( unsigned char byEpIdx, unsigned char byStatus);
+  void pdiAcknowledgeSetup( void);
+  void pdiClearBuffer( void);
+  void pdiValidateBuffer( void);
+
+  void pdiSendResume( void);
+  unsigned short pdiGetFrameNumber( void);
+  unsigned short pdiGetChipID( void); // this function is undocumented
+  
+ // HUB command
+ #if defined(PDIUSBH11) || defined(PDIUSBH11A)
+  void pdiClearPortFeature( unsigned char byEpIdx, unsigned char byFeature);
+  void pdiSetPortFeature( unsigned char byEpIdx, unsigned char byFeature);
+  unsigned short pdiGetPortFeature( unsigned char byEpIdx);
+  void pdiSetStatusChangeBits( unsigned char byBits);
+ #endif
+
+// PDIUSB other commands
+ void pdiWriteEndpoint( unsigned char byEpIdx, unsigned char byLength, const unsigned char *pbyData);
+ unsigned char pdiReadEndpoint( unsigned char byEpIdx, unsigned char byMaxLength, unsigned char *pbyData);
+ unsigned char pdiCmdData( unsigned char byCmd, unsigned char *pbyData,
+                           unsigned char byCount, unsigned char byRead);
+ void pdiInit( void);
+#if !defined(PDIUSBH11A_MULTIPLE)
+ void pdiAckSetupControl( void);
+#else
+ void pdiAckSetupFncControl( unsigned char Fnc);
+#endif
+
+unsigned char pdiEp2Idx(unsigned char ep);
+
+/*********************************************************/
+#endif // from _PDI_ERROR_NO_CONTINUE
+/*********************************************************/
+#endif // from _PDI_BASE_MODULE
index 2123ba7ca7376212b80346e658ecc94a1e0d5bb1..100968987d91a187d6b8a65abd9456aac682f122 100644 (file)
@@ -263,4 +263,20 @@ extern can_spinlock_t can_irq_manipulation_lock;
 
 #endif /*CAN_WITH_RTL*/
 
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,4))
+       #include <linux/kthread.h>
+       #define can_kthread_create      kthread_create
+       #define can_kthread_run kthread_run
+       #define can_kthread_bind        kthread_bind
+       #define can_kthread_stop        kthread_stop
+       #define can_kthread_should_stop kthread_should_stop
+#else
+       #define can_kthread_create
+       #define can_kthread_run
+       #define can_kthread_bind
+       #define can_kthread_stop
+       #define can_kthread_should_stop
+#endif
+
+
 #endif /*_CAN_SYSDEP_H*/
index 651d0c2b0b5da49563a8599a38c550d46946e492..f360dcf5b1539f69308a65e37ebde60f341a4808 100644 (file)
@@ -512,3 +512,6 @@ void can_filltimestamp(canmsg_tstamp_t *ptimestamp)
 #ifdef CAN_WITH_RTL
 extern int can_rtl_priority;
 #endif /*CAN_WITH_RTL*/
+
+extern struct candevice_t* register_usbdev(const char *hwname,void *devdata,void (*chipdataregfnc)(struct canchip_t *chip,void *data));
+extern void cleanup_usbdev(struct candevice_t *dev);
index a89f45a6fb628807f68c9b848cd0bbaa61b418e2..504b58a1775e38902bd2fc80f5335eab8ad86d5f 100644 (file)
@@ -11,7 +11,9 @@
 #include "./constants.h"
 
 int can_init_procdir(void);
+int can_init_procentry(int board);
 int can_delete_procdir(void);
+int can_delete_procentry(struct candevice_t *candev);
 
 struct canproc_t {
        struct proc_dir_entry *can_proc_entry;
index d35a8b1e51192a7d0fd270749478a7479a79cfb8..d07e3fda26637b14fd6f43c5390b688e7a389559 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 int init_hw_struct(void);
+int init_new_hw_struct(int devnr);
 int list_hw(void);
 void *can_checked_malloc(size_t size);
 int can_checked_free(void *address_p);
diff --git a/lincan/include/usbcan.h b/lincan/include/usbcan.h
new file mode 100644 (file)
index 0000000..36c3753
--- /dev/null
@@ -0,0 +1,188 @@
+/* usbcan.h
+ * Header file for the Linux CAN-bus driver.
+ * Written by Jan Kriz email:johen@post.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.3  17 Jul 2008
+ */
+
+#ifndef USBCAN_H
+#define USBCAN_H
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/kref.h>
+#include <asm/uaccess.h>
+#include <linux/usb.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+
+#include "../include/kthread.h"
+
+/* our private defines. if this grows any larger, use your own .h file */
+#define MAX_TRANSFER           (PAGE_SIZE - 512)
+/* MAX_TRANSFER is chosen so that the VM is not stressed by
+   allocations > PAGE_SIZE and the number of packets in a page
+   is an integer 512 is the largest possible packet on EHCI */
+#define WRITES_IN_FLIGHT       8
+/* arbitrarily chosen */
+
+/* Define these values to match your devices */
+#define USBCAN_VENDOR_ID       0x1669
+#define USBCAN_PRODUCT_ID      0x1011
+
+#define RESET_ADDR 0x0
+
+/*
+ * IO_RANGE is the io-memory range that gets reserved, please adjust according
+ * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
+ * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
+ */
+#define IO_RANGE 0x100
+
+
+int usbcan_request_io(struct candevice_t *candev);
+int usbcan_release_io(struct candevice_t *candev);
+int usbcan_reset(struct candevice_t *candev);
+int usbcan_init_hw_data(struct candevice_t *candev);
+int usbcan_init_chip_data(struct candevice_t *candev, int chipnr);
+int usbcan_init_obj_data(struct canchip_t *chip, int objnr);
+void usbcan_write_register(unsigned data, unsigned long address);
+unsigned usbcan_read_register(unsigned long address);
+int usbcan_program_irq(struct candevice_t *candev);
+int usbcan_register(struct hwspecops_t *hwspecops);
+
+int usbcan_chip_config(struct canchip_t *chip);
+int usbcan_extended_mask(struct canchip_t *chip, unsigned long code, unsigned long mask);
+int usbcan_baud_rate(struct canchip_t *chip, int rate, int clock, int sjw,
+               int sampl_pt, int flags);
+int usbcan_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj);
+int usbcan_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj,
+               struct canmsg_t *msg);
+int usbcan_send_msg(struct canchip_t *chip, struct msgobj_t *obj,
+               struct canmsg_t *msg);
+int usbcan_fill_chipspecops(struct canchip_t *chip);
+int usbcan_irq_handler(int irq, struct canchip_t *chip);
+
+int usbcan_init(void);
+void usbcan_exit(void);
+
+int usbcan_kthread(void *data);
+int usbcan_chip_queue_status(struct canchip_t *chip);
+
+#ifdef CONFIG_OC_LINCAN_DETAILED_ERRORS
+
+// static const char *sja1000_ecc_errc_str[]={
+//     "bit error",
+//     "form error",
+//     "stuff error",
+//     "other type of error"
+// };
+//
+// static const char *sja1000_ecc_seg_str[]={
+//     "?0?",
+//     "?1?",
+//     "ID.28 to ID.21",
+//     "start of frame",
+//     "bit SRTR",
+//     "bit IDE",
+//     "ID.20 to ID.18",
+//     "ID.17 to ID.13",
+//     "CRC sequence",
+//     "reserved bit 0",
+//     "data field",
+//     "data length code",
+//     "bit RTR",
+//     "reserved bit 1",
+//     "ID.4 to ID.0",
+//     "ID.12 to ID.5",
+//     "?16?"
+//     "active error flag",
+//     "intermission",
+//     "tolerate dominant bits",
+//     "?20?",
+//     "?21?",
+//     "passive error flag",
+//     "error delimiter",
+//     "CRC delimiter",
+//     "acknowledge slot",
+//     "end of frame",
+//     "acknowledge delimiter",
+//     "overload flag",
+//     "?29?",
+//     "?30?",
+//     "?31?"
+// };
+
+#endif /*CONFIG_OC_LINCAN_DETAILED_ERRORS*/
+
+struct usbcan_usb;
+
+#define USBCAN_TOT_RX_URBS 8
+#define USBCAN_TOT_TX_URBS 8
+
+#define USBCAN_TRANSFER_SIZE 16
+
+struct usbcan_message {
+       struct urb      *u;
+       struct usbcan_usb *dev;
+       u8      msg[USBCAN_TRANSFER_SIZE];
+       spinlock_t              acc;            /* access lock */
+       struct canque_edge_t *qedge;
+       struct canque_slot_t *slot;
+       volatile long   flags;
+};
+
+#define USBCAN_MESSAGE_FREE                                    (1)
+#define USBCAN_MESSAGE_URB_PENDING             (2)
+#define USBCAN_MESSAGE_TERMINATE                       (3)
+#define USBCAN_MESSAGE_ERROR                                   (4)
+#define USBCAN_MESSAGE_DATA_OK                         (5)
+#define USBCAN_MESSAGE_TYPE_RX                         (6)
+#define USBCAN_MESSAGE_TYPE_TX                         (7)
+
+/* Structure to hold all of our device specific stuff */
+struct usbcan_usb {
+       struct usb_device       *udev;                  /* the usb device for this device */
+       struct usb_interface    *interface;             /* the interface for this device */
+       unsigned char           *bulk_in_buffer;        /* the buffer to receive data */
+       size_t                  bulk_in_size;           /* the size of the receive buffer */
+       u8                      bulk_in_endpointAddr;   /* the address of the bulk in endpoint */
+       u8                      bulk_out_endpointAddr;  /* the address of the bulk out endpoint */
+       struct mutex            io_mutex;               /* synchronize I/O with disconnect */
+       struct usbcan_message   rx[USBCAN_TOT_RX_URBS];
+       struct usbcan_message   tx[USBCAN_TOT_TX_URBS];
+
+       struct task_struct *comthread;                      /* usb communication kernel thread  */
+       wait_queue_head_t queue;
+
+       struct canchip_t *chip;
+       volatile long flags;
+};
+
+#define USBCAN_DATA_OK                         (1)
+#define USBCAN_DATA_RX                         (2)
+#define USBCAN_DATA_TX                         (3)
+#define USBCAN_TERMINATE                       (4)
+#define USBCAN_ERROR                                   (5)
+#define USBCAN_TX_PENDING                      (6)
+#define USBCAN_THREAD_RUNNING  (7)
+#define USBCAN_FREE_TX_URB             (8)
+
+#define USBCAN_VENDOR_BAUD_RATE_SET    (1)
+#define USBCAN_VENDOR_BAUD_RATE_STATUS (2)
+#define USBCAN_VENDOR_SET_BTREGS       (3)
+#define USBCAN_VENDOR_CHECK_TX_STAT    (4)
+#define USBCAN_VENDOR_START_CHIP       (5)
+#define USBCAN_VENDOR_STOP_CHIP        (6)
+#define USBCAN_VENDOR_EXT_MASK_SET     (7)
+#define USBCAN_VENDOR_EXT_MASK_STATUS  (8)
+
+struct usbcan_devs {
+       struct usbcan_usb **devs;
+       int     count;
+       struct candevice_t *candev;
+};
+
+
+#endif /*USBCAN_H*/
index 38a2ba238c8cebb39b5067b2c593c8d93f874fd0..72d28119624a903bb4a65fe81623fd214ee3a7a6 100644 (file)
@@ -1,6 +1,6 @@
 lincan_cards_NAMES = pip pccan smartcan nsi cc_can104 ems_cpcpci \
                pc_i03 pcm3680 aim104 m437 pcccan ssv bfadcan gensja1000io pikronisa eb8245 \
-               kv_pcican msmcan oscar adlink7841 pcan_pci esdpci200 unican virtual template
+               kv_pcican msmcan oscar adlink7841 pcan_pci esdpci200 unican usbcan virtual template
 
 lincan_morecards_NAMES = hms30c7202_can ns_dev_can ipci165 pimx1 tscan1 nsi_canpci sh7760
 
@@ -37,6 +37,10 @@ ifeq ($(CONFIG_OC_LINCAN_CARD_sh7760),y)
 lincan_cards_SOURCES += sh7760.c
 endif
 
+ifeq ($(CONFIG_OC_LINCAN_CARD_usbcan),y)
+lincan_cards_SOURCES += kthread.c
+endif
+
 ifneq ($(filter hms30c7202_can ns_dev_can,$(lincan_cards_SELECTED)),)
 $(warning Not finished C_CAN support requested)
 lincan_cards_SOURCES += c_can.c c_can_irq.c
index a7cef368669dfb126f1def6836ad50049c605323..0c2696ac64fea3df7acfe564e80c4ab68894188d 100644 (file)
@@ -45,6 +45,7 @@ extern int ts7kv_register(struct hwspecops_t *hwspecops);
 extern int ns_dev_register(struct hwspecops_t *hwspecops);
 extern int hms30c7202_register(struct hwspecops_t *hwspecops);
 extern int nsi_canpci_register(struct hwspecops_t *hwspecops);
+extern int usbcan_register(struct hwspecops_t *hwspecops);
 extern int pcan_pci_register(struct hwspecops_t *hwspecops);
 extern int esdpci200_register(struct hwspecops_t *hwspecops);
 extern int sh7760_register(struct hwspecops_t *hwspecops);
@@ -163,6 +164,9 @@ const struct boardtype_t can_boardtypes[]={
     #endif
     #if defined(CONFIG_OC_LINCAN_CARD_pcan_pci)&&defined(CAN_ENABLE_PCI_SUPPORT)
        {"pcan_pci", pcan_pci_register, 0},
+    #endif
+    #if defined(CONFIG_OC_LINCAN_CARD_usbcan)
+       {"usbcan", usbcan_register, 0},
     #endif
        {NULL}
 };
index d25e936461637911b8dccbea231ed8b66db982d0..5e789ae4e56bb36881f5772727389ae9edd85c25 100644 (file)
@@ -14,7 +14,7 @@
 #include "../include/finish.h"
 #include "../include/setup.h"
 
-
+extern int next_minor;
 /**
  * msgobj_done - destroys one CAN message object
  * @obj: pointer to CAN message object structure
@@ -37,8 +37,11 @@ void msgobj_done(struct msgobj_t *obj)
        }
 
        if((obj->minor>=0)) {
-               if(objects_p[obj->minor] == obj)
+               if(objects_p[obj->minor] == obj){
                        objects_p[obj->minor] = NULL;
+                       if (--next_minor<0)
+                               next_minor=0;
+               }
                else
                        CANMSG("msgobj_done: not registered as minor\n");
        }
@@ -127,7 +130,7 @@ void canhardware_done(struct canhardware_t *canhw)
        int i;
        struct candevice_t *candev;
 
-       for(i=0; i<canhw->nr_boards; i++){
+       for(i=0; i<MAX_HW_CARDS; i++){
                if((candev=canhw->candevice[i])==NULL)
                        continue;
                candevice_done(candev);
index c0c6d0085d2a9a69af16352fdc86225a024606b5..b8edf46f5c37a3b7f59f1f91f36f5862bf1a645b 100644 (file)
 #include "../include/can_iortl.h"
 #endif /*CAN_WITH_RTL*/
 
+#if defined(CONFIG_OC_LINCAN_CARD_usbcan)
+       #include "../include/usbcan.h"
+#endif
+
 can_spinlock_t canuser_manipulation_lock;
 
 int major=CAN_MAJOR;
@@ -362,6 +366,15 @@ int init_module(void)
                }
         }
 #endif
+
+#if defined(CONFIG_OC_LINCAN_CARD_usbcan)
+       res = usbcan_init();
+       if (res){
+               CANMSG("usb_register for usbcan failed. Error number %d.\n", res);
+               return -ENODEV;
+       }
+#endif
+
        return 0;
 
 #ifdef CONFIG_PROC_FS
@@ -400,12 +413,225 @@ int init_module(void)
                return -ENODEV;
 }
 
+
+
+
+
+struct candevice_t* register_usbdev(const char *hwname,void *devdata,void (*chipdataregfnc)(struct canchip_t *ch,void *data)){
+       int i=0, j, board=0;
+       struct candevice_t *candev;
+       struct canchip_t *chip;
+       struct boardtype_t *brp;
+
+       while ( (hw[board] != NULL) && (board < MAX_HW_CARDS) )
+               board++;
+       if (board>=MAX_HW_CARDS){
+               CANMSG("Maximum number of devices has been reached, no space for new device");
+               return NULL;
+       }
+       brp = boardtype_find(hwname);
+       if(!brp) {
+               CANMSG("Sorry, hardware \"%s\" is currently not supported.\n",hw[board]);
+               return NULL;
+       }
+       if (board==MAX_HW_CARDS){
+                       CANMSG("Device \"%s\" could not be registered due to internal limits.\n",hw[board]);
+                       return NULL;
+       }
+       hw[board]=brp->boardtype;
+
+       if (init_new_hw_struct(board))
+               return NULL;
+
+       #ifdef CAN_DEBUG
+               list_hw();
+       #endif
+
+       candev=hardware_p->candevice[board];
+
+       /* Adding link to usb device structure into can device */
+       candev->sysdevptr.anydev=devdata;
+
+       if (candev->hwspecops->request_io(candev))
+               goto request_io_error;
+       candev->flags|=CANDEV_IO_RESERVED;
+
+       if (candev->hwspecops->reset(candev))
+               goto reset_error;
+
+       for(j=0; j<candev->nr_all_chips; j++) {
+               if((chip=candev->chip[j])==NULL)
+                       continue;
+
+               chipdataregfnc(chip,devdata);
+
+               if(chip->chipspecops->attach_to_chip(chip)<0) {
+                       CANMSG("Initial attach to the chip HW failed\n");
+                       goto interrupt_error;
+               }
+
+               chip->flags |= CHIP_ATTACHED;
+
+               if(can_chip_setup_irq(chip)<0) {
+                       CANMSG("Error to setup chip IRQ\n");
+                       goto interrupt_error;
+               }
+       }
+
+       if (candev->flags & CANDEV_PROGRAMMABLE_IRQ)
+               if (candev->hwspecops->program_irq(candev)){
+                       CANMSG("Error to program board interrupt\n");
+                       goto interrupt_error;
+               }
+
+#ifdef CONFIG_PROC_FS
+       if (can_init_procentry(board))
+               goto proc_error;
+#endif
+
+#if defined(CONFIG_DEVFS_FS) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+       {
+               #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,0))
+               char dev_name[32];
+               #else
+               struct class_device *this_dev;
+               #endif
+               int dev_minor;
+               for(i=0;i<MAX_TOT_MSGOBJS;i++) {
+                       if(!objects_p[i]) continue;
+                       if(objects_p[i]->hostchip->hostdevice != candev) continue;
+
+                       dev_minor=objects_p[i]->minor;
+                       #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,0))
+                       sprintf (dev_name, "can%d", dev_minor);
+                       devfs_handles[i]=devfs_register(NULL, dev_name,
+                       DEVFS_FL_DEFAULT, major, dev_minor,
+                       S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
+                       &can_fops, (void*)objects_p[i]);
+                       #else
+                       #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,14))
+                       this_dev=class_device_create(can_class, MKDEV(major, dev_minor), NULL,  "can%d", dev_minor);
+                       #elif  LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25) /* >= 2.6.15 */
+                       this_dev=class_device_create(can_class, NULL, MKDEV(major, dev_minor), NULL,  "can%d", dev_minor);
+                       #else /* >= 2.6.26 */
+                       this_dev=device_create_drvdata(can_class, NULL, MKDEV(major, dev_minor), objects_p[i],  "can%d", dev_minor);
+                       #endif /* >= 2.6.26 */
+                       if(IS_ERR(this_dev)){
+                               CANMSG("problem to create device \"can%d\" in the class \"can\"\n", dev_minor);
+                     #if  LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
+                       }else{
+                               /*this_dev->class_data=objects_p[i];*/
+                               class_set_devdata(this_dev,objects_p[i]);
+                     #endif /* <= 2.6.25 */
+                       }
+                       #ifdef CONFIG_DEVFS_FS
+                       devfs_mk_cdev(MKDEV(major, dev_minor), S_IFCHR | S_IRUGO | S_IWUGO, "can%d", dev_minor);
+                       #endif
+                       #endif
+               }
+       }
+#endif
+       return candev;
+
+#ifdef CONFIG_PROC_FS
+       proc_error: ;
+               CANMSG("Error registering /proc entry.\n");
+               goto memory_error;
+#endif
+
+       interrupt_error: ;
+               goto memory_error;
+
+       reset_error: ;
+               CANMSG("Error resetting device.\n");
+               goto memory_error;
+
+       request_io_error: ;
+               CANMSG("Error to request IO resources for device.\n");
+               goto memory_error;
+
+       memory_error: ;
+
+               #ifdef CAN_WITH_RTL
+       rtldev_error:
+               #endif /*CAN_WITH_RTL*/
+
+//     register_error:
+               if ( can_del_mem_list() )
+                       CANMSG("Error deallocating memory\n");
+
+               return NULL;
+}
+
+
+
+
+
+
+
+void cleanup_usbdev(struct candevice_t *dev)
+{
+       int i=0;
+       int dev_minor;
+
+       if (!dev)
+               return;
+
+#ifdef CONFIG_PROC_FS
+       if (can_delete_procentry(dev))
+               CANMSG("Error unregistering /proc/can entry.\n");
+#endif
+
+#if defined(CONFIG_DEVFS_FS) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+       for(i=0;i<MAX_TOT_MSGOBJS;i++) {
+               if(!objects_p[i]) continue;
+               if(objects_p[i]->hostchip->hostdevice != dev) continue;
+               #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,0))
+               if(devfs_handles[i])
+                       devfs_unregister(devfs_handles[i]);
+               #else
+               dev_minor=objects_p[i]->minor;
+               if(dev_minor>=0){
+                       #ifdef CONFIG_DEVFS_FS
+                       devfs_remove("can%d", dev_minor);
+                       #endif
+                       #if  LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
+                       class_device_destroy(can_class, MKDEV(major, dev_minor));
+                       #else /* >= 2.6.26 */
+                       device_destroy(can_class, MKDEV(major, dev_minor));
+                       #endif /* >= 2.6.26 */
+               }
+               #endif
+       }
+#endif
+
+       for(i=0;i<MAX_TOT_CHIPS;i++){
+               if(!chips_p[i]) continue;
+               if(chips_p[i]->hostdevice != dev) continue;
+               chips_p[i]=NULL;
+       }
+
+       hardware_p->candevice[dev->candev_idx]=NULL;
+       hardware_p->nr_boards--;
+       hw[dev->candev_idx]=NULL;
+
+       candevice_done(dev);
+       can_checked_free(dev);
+}
+
+
+
+
 void cleanup_module(void)
 {
 #if defined(CONFIG_DEVFS_FS) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
        int i=0;
 #endif
 
+#if defined(CONFIG_OC_LINCAN_CARD_usbcan)
+       usbcan_exit();
+#endif
+
 #ifdef CONFIG_PROC_FS
        if (can_delete_procdir())
                CANMSG("Error unregistering /proc/can entry.\n");
index a0aad042446b96d5f4a634da866e8e245b138291..c53971f790a4a5c8ab30e72fd13449d013849aa9 100644 (file)
@@ -19,9 +19,10 @@ int parse_mod_parms(void)
        const struct boardtype_t *brp;
 
        if ( (hw[0] == NULL) | (io[0] == -1) ) {
-               CANMSG("You must supply your type of hardware, interrupt numbers and io address.\n");
+               //CANMSG("You must supply your type of hardware, interrupt numbers and io address.\n");
+               CANMSG("Autodetection works only for USB devices, supply your type of hardware for PCI devices \n");
                CANMSG("Example: # insmod lincan.ko hw=pip5 irq=4 io=0x8000\n");
-               return -ENODEV;
+               //return -ENODEV;
        }
 
        while ( (hw[i] != NULL) && (i < MAX_HW_CARDS) ) {
index 4fb2343bf18fa43f7af4da87a58c2e749179e07a..e423b92725abca0012a166c2b1315554b03246fd 100644 (file)
 
 #define __NO_VERSION__
 #include <linux/module.h>
+#include <linux/mutex.h>
 
 int add_channel_to_procdir(struct candevice_t *candev);
-int remove_channel_from_procdir(void);
+int remove_channels_from_procdir(void);
+int remove_channel_from_procdir(struct candevice_t *candev);
 int add_object_to_procdir(int chip_nr);
 int remove_object_from_procdir(int chip_nr);
 
@@ -35,6 +37,7 @@ static int cc=0; /* static counter for each CAN chip */
 
 static struct canproc_t can_proc_base;
 static struct canproc_t *base=&can_proc_base;
+DEFINE_MUTEX(proc_mutex);              /* synchronize access to canproc_t array */
 
 /* The following functions are needed only for kernel version 2.2. Kernel
  * version 2.4 already defines them for us.
@@ -155,6 +158,9 @@ int can_init_procdir(void)
 {
        int board;
        struct candevice_t *candev;
+
+       mutex_init(&proc_mutex);
+
        base->can_proc_entry = can_create_proc_entry("can", S_IFDIR | S_IRUGO |
                                        S_IXUGO, CAN_PROC_ROOT);
        if (base->can_proc_entry == NULL)
@@ -168,13 +174,34 @@ int can_init_procdir(void)
        return 0;
 }
 
+/* can_init_procentry registers entry of a new board in CAN directory tree at
+ * the proc system.
+ */
+int can_init_procentry(int board)
+{
+       struct candevice_t *candev;
+       candev=hardware_p->candevice[board];
+       if(candev)
+               return add_channel_to_procdir(candev);
+       return -ENODEV;
+}
+
 /* can_delete_procdir removes the entire CAN tree from the proc system */
 int can_delete_procdir(void)
 {
-       if (remove_channel_from_procdir()) 
+       if (remove_channels_from_procdir())
                return -ENODEV;
        /* name: "can" */
-       if (can_remove_proc_entry(base->can_proc_entry, CAN_PROC_ROOT)) 
+       if (can_remove_proc_entry(base->can_proc_entry, CAN_PROC_ROOT))
+               return -ENODEV;
+
+       return 0;
+}
+
+/* can_delete_procentry removes device entries from CAN tree in the proc system */
+int can_delete_procentry(struct candevice_t *candev)
+{
+       if (remove_channel_from_procdir(candev))
                return -ENODEV;
 
        return 0;
@@ -214,58 +241,108 @@ int add_channel_to_procdir(struct candevice_t *candev)
 {
        int i=0;
 
-       for (i=0; i < candev->nr_all_chips; i++) {
+       mutex_lock(&proc_mutex);
+       for (i=0; i < MAX_TOT_CHIPS; i++){
+               if (!chips_p[i]) continue;
+               if (chips_p[i]->hostdevice != candev) continue;
 
-               base->channel[cc] = (struct channelproc_t *)
+               base->channel[i] = (struct channelproc_t *)
                        can_checked_malloc(sizeof(struct channelproc_t));
-               if (base->channel[cc] == NULL)
+               if (base->channel[i] == NULL){
+                       mutex_unlock(&proc_mutex);
                        return -ENOMEM;
+               }
 
-               sprintf(base->channel[cc]->ch_name, "channel%d",cc);
+               sprintf(base->channel[i]->ch_name, "channel%d",i);
 
-               base->channel[cc]->ch_entry = can_create_proc_entry(
-                                               base->channel[cc]->ch_name,
+               base->channel[i]->ch_entry = can_create_proc_entry(
+                                               base->channel[i]->ch_name,
                                                S_IFDIR | S_IRUGO |S_IXUGO,
                                                base->can_proc_entry);
 
-               if (base->channel[cc]->ch_entry == NULL)
+               if (base->channel[i]->ch_entry == NULL){
+                       mutex_unlock(&proc_mutex);
                        return -ENODEV;
+               }
 
-               add_object_to_procdir(cc);
+               add_object_to_procdir(i);
 
                create_proc_read_entry("chip_info",        /* proc entry name */
                                       0,                  /* protection mask, 0->default */
-                                      base->channel[cc]->ch_entry,  /* parent dir, NULL->/proc */
+                                      base->channel[i]->ch_entry,  /* parent dir, NULL->/proc */
                                       can_chip_procinfo,
-                                      candev->chip[i]);
-
+                                      chips_p[i]);
                cc++;
        }
+       mutex_unlock(&proc_mutex);
 
        return 0;
 }
 
-int remove_channel_from_procdir(void)
+int remove_channels_from_procdir(void)
 {
+       int i=0;
+
+       mutex_lock(&proc_mutex);
+       for (i=0; i < MAX_TOT_CHIPS; i++){
+               if (!chips_p[i]) continue;
 
-       while (cc != 0) {
                cc--;
 
-               if(!base->channel[cc]) continue;
+               if(!base->channel[i]) continue;
 
-               remove_proc_entry("chip_info", base->channel[cc]->ch_entry);
+               remove_proc_entry("chip_info", base->channel[i]->ch_entry);
 
-               if (remove_object_from_procdir(cc))
+               if (remove_object_from_procdir(i)){
+                       mutex_unlock(&proc_mutex);
                        return -ENODEV;
+               }
 
                /* name: base->channel[cc]->ch_name */
-               if (can_remove_proc_entry(base->channel[cc]->ch_entry,
-                                                       base->can_proc_entry))
+               if (can_remove_proc_entry(base->channel[i]->ch_entry,
+                                                       base->can_proc_entry)){
+                       mutex_unlock(&proc_mutex);
                        return -ENODEV;
+               }
 
-               can_checked_free(base->channel[cc]);
-               base->channel[cc] = NULL;
+               can_checked_free(base->channel[i]);
+               base->channel[i] = NULL;
+       }
+       mutex_unlock(&proc_mutex);
+
+       return 0;
+}
+
+int remove_channel_from_procdir(struct candevice_t *candev)
+{
+       int i=0,j=0;
+
+       mutex_lock(&proc_mutex);
+       for (i=0; i < MAX_TOT_CHIPS; i++){
+               if (!chips_p[i]) continue;
+               if (chips_p[i]->hostdevice != candev) continue;
+               if (!base->channel[i]) continue;
+
+               remove_proc_entry("chip_info", base->channel[i]->ch_entry);
+
+               if (remove_object_from_procdir(i)){
+                       mutex_unlock(&proc_mutex);
+                       return -ENODEV;
+               }
+
+               /* name: base->channel[cc]->ch_name */
+               if (can_remove_proc_entry(base->channel[i]->ch_entry,
+                                                       base->can_proc_entry)){
+                       mutex_unlock(&proc_mutex);
+                       return -ENODEV;
+               }
+
+               can_checked_free(base->channel[i]);
+               base->channel[i] = NULL;
+
+               cc--;
        }
+       mutex_unlock(&proc_mutex);
 
        return 0;
 }
index 64c67bef105931e14d77303671d81802b2ddabf3..cb6550d3149a47f0aaa17502dae5e62fe10b0210 100644 (file)
@@ -19,6 +19,8 @@ int init_device_struct(int card, int *chan_param_idx_p, int *irq_param_idx_p);
 int init_chip_struct(struct candevice_t *candev, int chipnr, int irq, long baudrate, long clock);
 int init_obj_struct(struct candevice_t *candev, struct canchip_t *hostchip, int objnr);
 
+int next_minor=0;
+
 /**
  * can_base_addr_fixup - relocates board physical memory addresses to the CPU accessible ones
  * @candev: pointer to the previously filled device/board, chips and message objects structures
@@ -78,7 +80,6 @@ int can_check_dev_taken(void *anydev)
  */
 int register_obj_struct(struct msgobj_t *obj, int minorbase)
 {
-       static int next_minor=0;
        int i;
 
        if(minorbase>=0)
@@ -156,6 +157,30 @@ int init_hw_struct(void)
        return 0;
 }
 
+/**
+ * init_new_hw_struct - initializes driver description structures for new hardware
+ *
+ * The function init_new_hw_struct() is used to initialize the hardware structure.
+ *
+ * Return Value: returns negative number in the case of fail
+ */
+int init_new_hw_struct(int devnr)
+{
+       int irq_param_idx=0;
+       int chan_param_idx=0;
+
+       if ( (hw[devnr] != NULL) & (devnr < MAX_HW_CARDS) ) {
+               hardware_p->nr_boards++;
+
+               if (init_device_struct(devnr, &chan_param_idx, &irq_param_idx)) {
+                       CANMSG("Error initializing candevice_t structures.\n");
+                       return -ENODEV;
+               }
+       }
+
+       return 0;
+}
+
 /**
  * init_device_struct - initializes single CAN device/board
  * @card: index into @hardware_p HW description
diff --git a/lincan/src/usbcan.c b/lincan/src/usbcan.c
new file mode 100644 (file)
index 0000000..b7b595f
--- /dev/null
@@ -0,0 +1,1395 @@
+/* usbcan.h
+ * Header file for the Linux CAN-bus driver.
+ * Written by Jan Kriz email:johen@post.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.3  17 Jul 2008
+ */
+
+#include "../include/can.h"
+#include "../include/can_sysdep.h"
+#include "../include/main.h"
+#include "../include/devcommon.h"
+#include "../include/setup.h"
+#include "../include/usbcan.h"
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
+ #include <linux/freezer.h>
+#endif
+
+static int usbcan_probe(struct usb_interface *interface, const struct usb_device_id *id);
+static void usbcan_disconnect(struct usb_interface *interface);
+
+volatile int usbcan_chip_count=0;
+
+/* table of devices that work with this driver */
+static struct usb_device_id usbcan_table [] = {
+       { USB_DEVICE(USBCAN_VENDOR_ID, USBCAN_PRODUCT_ID) },
+       { }                                     /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, usbcan_table);
+
+static struct usb_driver usbcan_driver = {
+       .name =         "usbcan",
+       .id_table = usbcan_table,
+       .probe =        usbcan_probe,
+       .disconnect =   usbcan_disconnect,
+};
+
+/**
+ * usbcan_request_io: - reserve io or memory range for can board
+ * @candev: pointer to candevice/board which asks for io. Field @io_addr
+ *     of @candev is used in most cases to define start of the range
+ *
+ * The function usbcan_request_io() is used to reserve the io-memory. If your
+ * hardware uses a dedicated memory range as hardware control registers you
+ * will have to add the code to reserve this memory as well.
+ * %IO_RANGE is the io-memory range that gets reserved, please adjust according
+ * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
+ * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
+ * Return Value: The function returns zero on success or %-ENODEV on failure
+ * File: src/usbcan.c
+ */
+int usbcan_request_io(struct candevice_t *candev)
+{
+       struct usbcan_devs *usbdevs = (struct usbcan_devs *)candev->sysdevptr.anydev;
+
+       if (!usbdevs){
+               CANMSG("USBCAN_REQUEST_IO: Cannot register usbcan while usb device is not present.\n");
+               CANMSG("USBCAN_REQUEST_IO: Usbcan registers automatically on device insertion.\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+/**
+ * usbcan_release_io - free reserved io memory range
+ * @candev: pointer to candevice/board which releases io
+ *
+ * The function usbcan_release_io() is used to free reserved io-memory.
+ * In case you have reserved more io memory, don't forget to free it here.
+ * IO_RANGE is the io-memory range that gets released, please adjust according
+ * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
+ * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
+ * Return Value: The function always returns zero
+ * File: src/usbcan.c
+ */
+int usbcan_release_io(struct candevice_t *candev)
+{
+       return 0;
+}
+
+/**
+ * usbcan_reset - hardware reset routine
+ * @candev: Pointer to candevice/board structure
+ *
+ * The function usbcan_reset() is used to give a hardware reset. This is
+ * rather hardware specific so I haven't included example code. Don't forget to
+ * check the reset status of the chip before returning.
+ * Return Value: The function returns zero on success or %-ENODEV on failure
+ * File: src/usbcan.c
+ */
+int usbcan_reset(struct candevice_t *candev)
+{
+       return 0;
+}
+
+/**
+ * usbcan_init_hw_data - Initialize hardware cards
+ * @candev: Pointer to candevice/board structure
+ *
+ * The function usbcan_init_hw_data() is used to initialize the hardware
+ * structure containing information about the installed CAN-board.
+ * %RESET_ADDR represents the io-address of the hardware reset register.
+ * %NR_82527 represents the number of Intel 82527 chips on the board.
+ * %NR_SJA1000 represents the number of Philips sja1000 chips on the board.
+ * The flags entry can currently only be %CANDEV_PROGRAMMABLE_IRQ to indicate that
+ * the hardware uses programmable interrupts.
+ * Return Value: The function always returns zero
+ * File: src/usbcan.c
+ */
+int usbcan_init_hw_data(struct candevice_t *candev)
+{
+       candev->res_addr=RESET_ADDR;
+       candev->nr_82527_chips=0;
+       candev->nr_sja1000_chips=0;
+       candev->nr_all_chips=usbcan_chip_count;
+       candev->flags |= CANDEV_PROGRAMMABLE_IRQ*0;
+
+       return 0;
+}
+
+/**
+ * usbcan_init_obj_data - Initialize message buffers
+ * @chip: Pointer to chip specific structure
+ * @objnr: Number of the message buffer
+ *
+ * The function usbcan_init_obj_data() is used to initialize the hardware
+ * structure containing information about the different message objects on the
+ * CAN chip. In case of the sja1000 there's only one message object but on the
+ * i82527 chip there are 15.
+ * The code below is for a i82527 chip and initializes the object base addresses
+ * The entry @obj_base_addr represents the first memory address of the message
+ * object. In case of the sja1000 @obj_base_addr is taken the same as the chips
+ * base address.
+ * Unless the hardware uses a segmented memory map, flags can be set zero.
+ * Return Value: The function always returns zero
+ * File: src/usbcan.c
+ */
+int usbcan_init_obj_data(struct canchip_t *chip, int objnr)
+{
+       chip->msgobj[objnr]->obj_base_addr=0;
+
+       return 0;
+}
+
+/**
+ * usbcan_program_irq - program interrupts
+ * @candev: Pointer to candevice/board structure
+ *
+ * The function usbcan_program_irq() is used for hardware that uses
+ * programmable interrupts. If your hardware doesn't use programmable interrupts
+ * you should not set the @candevices_t->flags entry to %CANDEV_PROGRAMMABLE_IRQ and
+ * leave this function unedited. Again this function is hardware specific so
+ * there's no example code.
+ * Return value: The function returns zero on success or %-ENODEV on failure
+ * File: src/usbcan.c
+ */
+int usbcan_program_irq(struct candevice_t *candev)
+{
+       return 0;
+}
+
+/* !!! Don't change this function !!! */
+int usbcan_register(struct hwspecops_t *hwspecops)
+{
+       hwspecops->request_io = usbcan_request_io;
+       hwspecops->release_io = usbcan_release_io;
+       hwspecops->reset = usbcan_reset;
+       hwspecops->init_hw_data = usbcan_init_hw_data;
+       hwspecops->init_chip_data = usbcan_init_chip_data;
+       hwspecops->init_obj_data = usbcan_init_obj_data;
+       hwspecops->write_register = NULL;
+       hwspecops->read_register = NULL;
+       hwspecops->program_irq = usbcan_program_irq;
+       return 0;
+}
+
+// static int sja1000_report_error_limit_counter;
+
+static void usbcan_report_error(struct canchip_t *chip,
+                               unsigned sr, unsigned ir, unsigned ecc)
+{
+       /*TODO : Error reporting from device */
+
+#if 0
+       if(sja1000_report_error_limit_counter>=100)
+               return;
+
+       CANMSG("Error: status register: 0x%x irq_register: 0x%02x error: 0x%02x\n",
+               sr, ir, ecc);
+
+       sja1000_report_error_limit_counter+=10;
+
+       if(sja1000_report_error_limit_counter>=100){
+               sja1000_report_error_limit_counter+=10;
+               CANMSG("Error: too many errors, reporting disabled\n");
+               return;
+       }
+
+#ifdef CONFIG_OC_LINCAN_DETAILED_ERRORS
+       CANMSG("SR: BS=%c  ES=%c  TS=%c  RS=%c  TCS=%c TBS=%c DOS=%c RBS=%c\n",
+               sr&sjaSR_BS?'1':'0',sr&sjaSR_ES?'1':'0',
+               sr&sjaSR_TS?'1':'0',sr&sjaSR_RS?'1':'0',
+               sr&sjaSR_TCS?'1':'0',sr&sjaSR_TBS?'1':'0',
+               sr&sjaSR_DOS?'1':'0',sr&sjaSR_RBS?'1':'0');
+       CANMSG("IR: BEI=%c ALI=%c EPI=%c WUI=%c DOI=%c EI=%c  TI=%c  RI=%c\n",
+               sr&sjaIR_BEI?'1':'0',sr&sjaIR_ALI?'1':'0',
+               sr&sjaIR_EPI?'1':'0',sr&sjaIR_WUI?'1':'0',
+               sr&sjaIR_DOI?'1':'0',sr&sjaIR_EI?'1':'0',
+               sr&sjaIR_TI?'1':'0',sr&sjaIR_RI?'1':'0');
+       if((sr&sjaIR_EI) || 1){
+               CANMSG("EI: %s %s %s\n",
+                      sja1000_ecc_errc_str[(ecc&(sjaECC_ERCC1|sjaECC_ERCC0))/sjaECC_ERCC0],
+                      ecc&sjaECC_DIR?"RX":"TX",
+                      sja1000_ecc_seg_str[ecc&sjaECC_SEG_M]
+                     );
+       }
+#endif /*CONFIG_OC_LINCAN_DETAILED_ERRORS*/
+#endif
+}
+
+
+/**
+ * usbcan_enable_configuration - enable chip configuration mode
+ * @chip: pointer to chip state structure
+ */
+int usbcan_enable_configuration(struct canchip_t *chip)
+{
+       return 0;
+}
+
+/**
+ * usbcan_disable_configuration - disable chip configuration mode
+ * @chip: pointer to chip state structure
+ */
+int usbcan_disable_configuration(struct canchip_t *chip)
+{
+       return 0;
+}
+
+/**
+ * usbcan_chip_config: - can chip configuration
+ * @chip: pointer to chip state structure
+ *
+ * This function configures chip and prepares it for message
+ * transmission and reception. The function resets chip,
+ * resets mask for acceptance of all messages by call to
+ * usbcan_extended_mask() function and then
+ * computes and sets baudrate with use of function usbcan_baud_rate().
+ * Return Value: negative value reports error.
+ * File: src/usbcan.c
+ */
+int usbcan_chip_config(struct canchip_t *chip)
+{
+       return 0;
+}
+
+/**
+ * usbcan_extended_mask: - setup of extended mask for message filtering
+ * @chip: pointer to chip state structure
+ * @code: can message acceptance code
+ * @mask: can message acceptance mask
+ *
+ * Return Value: negative value reports error.
+ * File: src/usbcan.c
+ */
+int usbcan_extended_mask(struct canchip_t *chip, unsigned long code, unsigned  long mask)
+{
+       int retval;
+       struct usbcan_usb *dev=(struct usbcan_usb*)chip->chip_data;
+
+       u8 usbbuf[USBCAN_TRANSFER_SIZE];
+
+       if (!dev)
+               return -ENODEV;
+
+       *(uint32_t *)(usbbuf)=cpu_to_le32(mask);
+       *(uint32_t *)(usbbuf+4)=cpu_to_le32(code);
+
+       retval=usb_control_msg(dev->udev,
+               usb_sndctrlpipe(dev->udev, 0),
+               USBCAN_VENDOR_EXT_MASK_SET,
+               USB_TYPE_VENDOR,
+               cpu_to_le16(0), cpu_to_le16(chip->chip_idx),
+               &usbbuf, USBCAN_TRANSFER_SIZE,
+               10000);
+       if (retval<0)
+               return -ENODEV;
+
+       retval = usb_control_msg(dev->udev,
+               usb_rcvctrlpipe(dev->udev, 0),
+               USBCAN_VENDOR_EXT_MASK_STATUS,
+               USB_TYPE_VENDOR,
+               cpu_to_le16(0), cpu_to_le16(chip->chip_idx),
+               &usbbuf, USBCAN_TRANSFER_SIZE,
+               10000);
+
+       if (retval==1){
+               if(usbbuf[0]==1){
+                       DEBUGMSG("Setting acceptance code to 0x%lx\n",(unsigned long)code);
+                       DEBUGMSG("Setting acceptance mask to 0x%lx\n",(unsigned long)mask);
+                       return 0;
+               }
+       }
+
+       CANMSG("Setting extended mask failed\n");
+       return -EINVAL;
+}
+
+/**
+ * usbcan_baud_rate: - set communication parameters.
+ * @chip: pointer to chip state structure
+ * @rate: baud rate in Hz
+ * @clock: frequency of sja1000 clock in Hz (ISA osc is 14318000)
+ * @sjw: synchronization jump width (0-3) prescaled clock cycles
+ * @sampl_pt: sample point in % (0-100) sets (TSEG1+1)/(TSEG1+TSEG2+2) ratio
+ * @flags: fields %BTR1_SAM, %OCMODE, %OCPOL, %OCTP, %OCTN, %CLK_OFF, %CBP
+ *
+ * Return Value: negative value reports error.
+ * File: src/usbcan.c
+ */
+int usbcan_baud_rate(struct canchip_t *chip, int rate, int clock, int sjw,
+                                                       int sampl_pt, int flags)
+{
+       int retval;
+       struct usbcan_usb *dev=(struct usbcan_usb*)chip->chip_data;
+
+       u8 usbbuf[USBCAN_TRANSFER_SIZE];
+
+       if (!dev)
+               return -ENODEV;
+
+       *(int32_t *)(usbbuf)=cpu_to_le32(rate);
+       *(int32_t *)(usbbuf+4)=cpu_to_le32(sjw);
+       *(int32_t *)(usbbuf+8)=cpu_to_le32(sampl_pt);
+       *(int32_t *)(usbbuf+12)=cpu_to_le32(flags);
+
+       retval=usb_control_msg(dev->udev,
+               usb_sndctrlpipe(dev->udev, 0),
+               USBCAN_VENDOR_BAUD_RATE_SET,
+               USB_TYPE_VENDOR,
+               cpu_to_le16(0), cpu_to_le16(chip->chip_idx),
+               &usbbuf, USBCAN_TRANSFER_SIZE,
+               10000);
+       if (retval<0)
+               return -ENODEV;
+
+       retval = usb_control_msg(dev->udev,
+               usb_rcvctrlpipe(dev->udev, 0),
+               USBCAN_VENDOR_BAUD_RATE_STATUS,
+               USB_TYPE_VENDOR,
+               cpu_to_le16(0), cpu_to_le16(chip->chip_idx),
+               usbbuf, USBCAN_TRANSFER_SIZE,
+               10000);
+
+       if (retval==1){
+               if(usbbuf[0]==1)
+                       return 0;
+       }
+
+       CANMSG("baud rate %d is not possible to set\n",
+               rate);
+       return -EINVAL;
+}
+
+/**
+ * usbcan_pre_read_config: - prepares message object for message reception
+ * @chip: pointer to chip state structure
+ * @obj: pointer to message object state structure
+ *
+ * Return Value: negative value reports error.
+ *     Positive value indicates immediate reception of message.
+ * File: src/usbcan.c
+ */
+int usbcan_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj)
+{
+       return 0;
+}
+
+#define MAX_TRANSMIT_WAIT_LOOPS 10
+/**
+ * usbcan_pre_write_config: - prepares message object for message transmission
+ * @chip: pointer to chip state structure
+ * @obj: pointer to message object state structure
+ * @msg: pointer to CAN message
+ *
+ * This function prepares selected message object for future initiation
+ * of message transmission by usbcan_send_msg() function.
+ * The CAN message data and message ID are transfered from @msg slot
+ * into chip buffer in this function.
+ * Return Value: negative value reports error.
+ * File: src/usbcan.c
+ */
+int usbcan_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj,
+                                                       struct canmsg_t *msg)
+{
+       return 0;
+}
+
+/**
+ * usbcan_send_msg: - initiate message transmission
+ * @chip: pointer to chip state structure
+ * @obj: pointer to message object state structure
+ * @msg: pointer to CAN message
+ *
+ * This function is called after usbcan_pre_write_config() function,
+ * which prepares data in chip buffer.
+ * Return Value: negative value reports error.
+ * File: src/usbcan.c
+ */
+int usbcan_send_msg(struct canchip_t *chip, struct msgobj_t *obj,
+                                                       struct canmsg_t *msg)
+{
+       return 0;
+}
+
+/**
+ * usbcan_check_tx_stat: - checks state of transmission engine
+ * @chip: pointer to chip state structure
+ *
+ * Return Value: negative value reports error.
+ *     Positive return value indicates transmission under way status.
+ *     Zero value indicates finishing of all issued transmission requests.
+ * File: src/usbcan.c
+ */
+int usbcan_check_tx_stat(struct canchip_t *chip)
+{
+       struct usbcan_usb *dev=(struct usbcan_usb*)chip->chip_data;
+       if (!dev)
+               return 0;
+       if (test_bit(USBCAN_TX_PENDING,&dev->flags))
+               return 1;
+       return 0;
+}
+
+/**
+ * usbcan_set_btregs: -  configures bitrate registers
+ * @chip: pointer to chip state structure
+ * @btr0: bitrate register 0
+ * @btr1: bitrate register 1
+ *
+ * Return Value: negative value reports error.
+ * File: src/usbcan.c
+ */
+int usbcan_set_btregs(struct canchip_t *chip, unsigned short btr0,
+                                                       unsigned short btr1)
+{
+       int retval;
+       u8      buf[USBCAN_TRANSFER_SIZE];
+       struct usbcan_usb *dev=(struct usbcan_usb*)chip->chip_data;
+       uint16_t value=(btr1&0xFF)<<8 | (btr0&0xFF);
+
+       if (!dev)
+               return -ENODEV;
+
+       retval = usb_control_msg(dev->udev,
+       usb_rcvctrlpipe(dev->udev, 0),
+       USBCAN_VENDOR_SET_BTREGS,
+       USB_TYPE_VENDOR,
+       cpu_to_le16(value), cpu_to_le16(chip->chip_idx),
+       &buf, USBCAN_TRANSFER_SIZE,
+       10000);
+
+       if (retval==1){
+               if(buf[0]==1)
+                       return 0;
+       }
+       return -ENODEV;
+}
+
+/**
+ * usbcan_start_chip: -  starts chip message processing
+ * @chip: pointer to chip state structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/usbcan.c
+ */
+int usbcan_start_chip(struct canchip_t *chip)
+{
+       int retval;
+       u8      buf[USBCAN_TRANSFER_SIZE];
+       struct usbcan_usb *dev=(struct usbcan_usb*)chip->chip_data;
+
+       if (!dev)
+               return -ENODEV;
+
+       retval = usb_control_msg(dev->udev,
+       usb_rcvctrlpipe(dev->udev, 0),
+       USBCAN_VENDOR_START_CHIP,
+       USB_TYPE_VENDOR,
+       cpu_to_le16(0), cpu_to_le16(chip->chip_idx),
+       &buf, USBCAN_TRANSFER_SIZE,
+       10000);
+
+       if (retval==1){
+               if(buf[0]==1)
+                       return 0;
+       }
+       return -ENODEV;
+}
+
+/**
+ * usbcan_chip_queue_status: -  gets queue status from usb device
+ * @chip: pointer to chip state structure
+ *
+ * Return Value: negative value reports error.
+ * 0 means queue is not full
+ * 1 means queue is full
+ * File: src/usbcan.c
+ */
+int usbcan_chip_queue_status(struct canchip_t *chip)
+{
+       int retval;
+       u8      buf[USBCAN_TRANSFER_SIZE];
+       struct usbcan_usb *dev=(struct usbcan_usb*)chip->chip_data;
+
+       if (!dev)
+               return -ENODEV;
+       retval = usb_control_msg(dev->udev,
+       usb_rcvctrlpipe(dev->udev, 0),
+       USBCAN_VENDOR_CHECK_TX_STAT,
+       USB_TYPE_VENDOR,
+       cpu_to_le16(0), cpu_to_le16(chip->chip_idx),
+       &buf, USBCAN_TRANSFER_SIZE,
+       10000);
+
+       if (retval==1){
+               CANMSG("Chip_queue_status: %d\n",buf[0]);
+               if(buf[0]==1)
+                       return 0;
+               if(buf[0]==0)
+                       return 1;
+       }
+       CANMSG("Chip_queue_status error: %d\n",retval);
+       return -ENODEV;
+}
+
+/**
+ * usbcan_stop_chip: -  stops chip message processing
+ * @chip: pointer to chip state structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/usbcan.c
+ */
+int usbcan_stop_chip(struct canchip_t *chip)
+{
+       int retval;
+       u8      buf[USBCAN_TRANSFER_SIZE];
+       struct usbcan_usb *dev=(struct usbcan_usb*)chip->chip_data;
+
+       if (!dev)
+               return -ENODEV;
+
+       retval = usb_control_msg(dev->udev,
+       usb_rcvctrlpipe(dev->udev, 0),
+       USBCAN_VENDOR_STOP_CHIP,
+       USB_TYPE_VENDOR,
+       cpu_to_le16(0), cpu_to_le16(chip->chip_idx),
+       &buf, USBCAN_TRANSFER_SIZE,
+       10000);
+
+       if (retval==1){
+               if(buf[0]==1)
+                       return 0;
+       }
+       return -ENODEV;
+}
+
+/**
+ * usbcan_register_devs: - attaches usb device data to the chip structure
+ * @chip: pointer to chip state structure
+ * @data: usb device data
+ *
+ * File: src/usbcan.c
+ */
+void usbcan_register_devs(struct canchip_t *chip,void *data){
+       struct usbcan_devs *usbdevs=(struct usbcan_devs *)data;
+       if (!usbdevs){
+           CANMSG("Bad structure given\n");
+           return;
+       }
+       if (chip->chip_idx>=usbdevs->count) {
+           CANMSG("Requested chip number is bigger than chip count\n");
+           return;
+       }
+
+       usbdevs->devs[chip->chip_idx]->chip=chip;
+       chip->chip_data=(void *)usbdevs->devs[chip->chip_idx];
+}
+
+/**
+ * usbcan_attach_to_chip: - attaches to the chip, setups registers and state
+ * @chip: pointer to chip state structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/usbcan.c
+ */
+int usbcan_attach_to_chip(struct canchip_t *chip)
+{
+       struct usbcan_usb *dev = (struct usbcan_usb *)chip->chip_data;
+
+       /* start kernel thread */
+       dev->comthread=can_kthread_run(usbcan_kthread, (void *)dev, "usbcan_%d",chip->chip_idx);
+
+       return 0;
+}
+
+/**
+ * usbcan_release_chip: - called before chip structure removal if %CHIP_ATTACHED is set
+ * @chip: pointer to chip state structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/usbcan.c
+ */
+int usbcan_release_chip(struct canchip_t *chip)
+{
+       struct usbcan_usb *dev = (struct usbcan_usb *)chip->chip_data;
+
+       usbcan_stop_chip(chip);
+
+       /* terminate the kernel thread */
+       set_bit(USBCAN_TERMINATE,&dev->flags);
+       wake_up_process(dev->comthread);
+//     can_kthread_stop(dev->comthread);
+
+       return 0;
+}
+
+/**
+ * usbcan_remote_request: - configures message object and asks for RTR message
+ * @chip: pointer to chip state structure
+ * @obj: pointer to message object structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/usbcan.c
+ */
+int usbcan_remote_request(struct canchip_t *chip, struct msgobj_t *obj)
+{
+       CANMSG("usbcan_remote_request not implemented\n");
+       return -ENOSYS;
+}
+
+/**
+ * usbcan_standard_mask: - setup of mask for message filtering
+ * @chip: pointer to chip state structure
+ * @code: can message acceptance code
+ * @mask: can message acceptance mask
+ *
+ * Return Value: negative value reports error.
+ * File: src/usbcan.c
+ */
+int usbcan_standard_mask(struct canchip_t *chip, unsigned short code,
+               unsigned short mask)
+{
+       CANMSG("usbcan_standard_mask not implemented\n");
+       return -ENOSYS;
+}
+
+/**
+ * usbcan_clear_objects: - clears state of all message object residing in chip
+ * @chip: pointer to chip state structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/usbcan.c
+ */
+int usbcan_clear_objects(struct canchip_t *chip)
+{
+       CANMSG("usbcan_clear_objects not implemented\n");
+       return -ENOSYS;
+}
+
+/**
+ * usbcan_config_irqs: - tunes chip hardware interrupt delivery
+ * @chip: pointer to chip state structure
+ * @irqs: requested chip IRQ configuration
+ *
+ * Return Value: negative value reports error.
+ * File: src/usbcan.c
+ */
+int usbcan_config_irqs(struct canchip_t *chip, short irqs)
+{
+       CANMSG("usbcan_config_irqs not implemented\n");
+       return -ENOSYS;
+}
+
+/**
+ * usbcan_kthread_read_handler: - part of kthread code responsible for receive completed events
+ * @dev: pointer to usb device related structure
+ * @obj: pointer to attached message object description
+ *
+ * The main purpose of this function is to read message from usb urb
+ * and transfer message contents to CAN queue ends.
+ * This subroutine is called by
+ * usbcan_kthread().
+ * File: src/usbcan.c
+ */
+void usbcan_kthread_read_handler(struct usbcan_usb *dev, struct msgobj_t *obj){
+       int i, j, len, retval;
+       CANMSG("USBCAN RX handler\n");
+       for (i=0;i<USBCAN_TOT_RX_URBS;i++){
+               if (test_and_clear_bit(USBCAN_MESSAGE_DATA_OK,&dev->rx[i].flags)){
+                       CANMSG("USBCAN Thread has received a message\n");
+                       if ((dev->chip)&&(dev->chip->flags & CHIP_CONFIGURED)){
+                               u8 *ptr;
+                               struct usbcan_message *mess=&dev->rx[i];
+
+                               len=*(u8 *)(mess->msg+1);
+                               if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH;
+                               obj->rx_msg.length = len;
+
+                               obj->rx_msg.flags=le16_to_cpu(*(u16 *)(mess->msg+2));
+                               obj->rx_msg.id=le32_to_cpu((*(u32 *)(mess->msg+4)));
+
+                               for(ptr=mess->msg+8,j=0; j < len; ptr++,j++) {
+                                       obj->rx_msg.data[j]=*ptr;
+                               }
+
+                               // fill CAN message timestamp
+                               can_filltimestamp(&obj->rx_msg.timestamp);
+                               canque_filter_msg2edges(obj->qends, &obj->rx_msg);
+                       }
+                       else
+                               CANMSG("Destination chip not found\n");
+               }
+               if (!test_bit(USBCAN_MESSAGE_URB_PENDING,&dev->rx[i].flags)){
+                       CANMSG("Renewing RX urb\n");
+                       retval = usb_submit_urb (dev->rx[i].u, GFP_KERNEL);
+                       if (retval<0){
+                               CANMSG("%d. URB error %d\n", i, retval);
+                               set_bit(USBCAN_ERROR,&dev->flags);
+                       }
+                       else
+                               set_bit(USBCAN_MESSAGE_URB_PENDING,&dev->rx[i].flags);
+               }
+       }
+}
+
+/**
+ * usbcan_kthread_write_handler: - part of kthread code responsible for transmit done events
+ * @dev: pointer to usb device related structure
+ * @obj: pointer to attached message object description
+ *
+ * The main purpose of this function is to free allocated resources on transmit done event
+ * This subroutine is called by
+ * usbcan_kthread().
+ * File: src/usbcan.c
+ */
+void usbcan_kthread_write_handler(struct usbcan_usb *dev, struct msgobj_t *obj){
+       int i;
+       CANMSG("USBCAN TX handler\n");
+       for (i=0;i<USBCAN_TOT_TX_URBS;i++){
+               if (test_and_clear_bit(USBCAN_MESSAGE_DATA_OK,&dev->tx[i].flags)){
+                       struct usbcan_message *mess=&dev->tx[i];
+                       CANMSG("USBCAN Message successfully sent\n");
+
+                       if(mess->slot){
+                               // Do local transmitted message distribution if enabled
+                               if (processlocal){
+                                       // fill CAN message timestamp
+                                       can_filltimestamp(&mess->slot->msg.timestamp);
+
+                                       mess->slot->msg.flags |= MSG_LOCAL;
+                                       canque_filter_msg2edges(obj->qends, &mess->slot->msg);
+                               }
+                               // Free transmitted slot
+                               canque_free_outslot(obj->qends, mess->qedge, mess->slot);
+                               mess->slot=NULL;
+                       }
+                       can_msgobj_clear_fl(obj,TX_PENDING);
+
+                       set_bit(USBCAN_FREE_TX_URB,&dev->flags);
+                       set_bit(USBCAN_MESSAGE_FREE,&dev->tx[i].flags);
+
+                       // Test if some new messages arrived
+                       set_bit(USBCAN_TX_PENDING,&dev->flags);
+               }
+       }
+}
+
+/**
+ * usbcan_kthread_write_request_handler: - part of kthread code responsible for sending transmit urbs
+ * @dev: pointer to usb device related structure
+ * @obj: pointer to attached message object description
+ *
+ * The main purpose of this function is to create a usb transmit safe object
+ * and send it via free transmit usb urb
+ * This subroutine is called by
+ * usbcan_kthread().
+ * File: src/usbcan.c
+ */
+void usbcan_kthread_write_request_handler(struct usbcan_usb *dev, struct msgobj_t *obj){
+       int i, j, cmd, len, retval;
+       for (i=0;i<USBCAN_TOT_TX_URBS;i++){
+               if (test_bit(USBCAN_MESSAGE_FREE,&dev->tx[i].flags)){
+                       struct usbcan_message *mess=&dev->tx[i];
+                       u8 *ptr;
+                       cmd=canque_test_outslot(obj->qends, &mess->qedge, &mess->slot);
+                       if(cmd>=0){
+                               CANMSG("USBCAN Sending a message\n");
+
+                               can_msgobj_set_fl(obj,TX_PENDING);
+                               clear_bit(USBCAN_FREE_TX_URB,&dev->flags);
+                               clear_bit(USBCAN_MESSAGE_FREE,&dev->tx[i].flags);
+
+                               *(u8 *)(mess->msg)=0;
+                               len = mess->slot->msg.length;
+                               if(len > CAN_MSG_LENGTH)
+                                       len = CAN_MSG_LENGTH;
+                               *(u8 *)(mess->msg+1)=len & 0xFF;
+                               *(u16 *)(mess->msg+2)=cpu_to_le16(mess->slot->msg.flags);
+                               *(u32 *)(mess->msg+4)=cpu_to_le32(mess->slot->msg.id);
+
+                               for(ptr=mess->msg+8,j=0; j < len; ptr++,j++) {
+                                       *ptr=mess->slot->msg.data[j] & 0xFF;
+                               }
+                               for(; j < 8; ptr++,j++) {
+                                       *ptr=0;
+                               }
+
+                               set_bit(USBCAN_MESSAGE_URB_PENDING,&mess->flags);
+                               retval = usb_submit_urb (dev->tx[i].u, GFP_KERNEL);
+                               if (retval){
+                                       CANMSG("%d. URB error %d\n",i,retval);
+                                       clear_bit(USBCAN_MESSAGE_URB_PENDING,&mess->flags);
+                                       set_bit(USBCAN_FREE_TX_URB,&dev->flags);
+                                       set_bit(USBCAN_MESSAGE_FREE,&dev->tx[i].flags);
+                                       obj->ret = -1;
+                                       canque_notify_inends(mess->qedge, CANQUEUE_NOTIFY_ERRTX_SEND);
+                                       canque_free_outslot(obj->qends, mess->qedge, mess->slot);
+                                       mess->slot=NULL;
+                               }
+                       }
+                       else{
+                               set_bit(USBCAN_FREE_TX_URB,&dev->flags);
+                               break;
+                       }
+               }
+       }
+}
+
+#define MAX_RETR 10
+
+/**
+ * usbcan_irq_handler: - interrupt service routine
+ * @irq: interrupt vector number, this value is system specific
+ * @chip: pointer to chip state structure
+ *
+ * Interrupt handler is activated when state of CAN controller chip changes,
+ * there is message to be read or there is more space for new messages or
+ * error occurs. The receive events results in reading of the message from
+ * CAN controller chip and distribution of message through attached
+ * message queues.
+ * File: src/usbcan.c
+ */
+int usbcan_irq_handler(int irq, struct canchip_t *chip)
+{
+       return CANCHIP_IRQ_HANDLED;
+}
+
+/**
+ * usbcan_wakeup_tx: - wakeups TX processing
+ * @chip: pointer to chip state structure
+ * @obj: pointer to message object structure
+ *
+ * Function is responsible for initiating message transmition.
+ * It is responsible for clearing of object TX_REQUEST flag
+ *
+ * Return Value: negative value reports error.
+ * File: src/usbcan.c
+ */
+int usbcan_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj)
+{
+       struct usbcan_usb *dev=(struct usbcan_usb *)chip->chip_data;
+
+       CANMSG("Trying to send message\n");
+       can_preempt_disable();
+
+       can_msgobj_set_fl(obj,TX_PENDING);
+       can_msgobj_set_fl(obj,TX_REQUEST);
+       while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
+               can_msgobj_clear_fl(obj,TX_REQUEST);
+
+               if (test_and_clear_bit(USBCAN_FREE_TX_URB,&dev->flags)){
+                       obj->tx_retry_cnt=0;
+                       set_bit(USBCAN_TX_PENDING,&dev->flags);
+                       if (test_bit(USBCAN_THREAD_RUNNING,&dev->flags))
+                               wake_up_process(dev->comthread);
+               }
+
+               can_msgobj_clear_fl(obj,TX_LOCK);
+               if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
+               CANMSG("TX looping in usbcan_wakeup_tx\n");
+       }
+
+       can_preempt_enable();
+       return 0;
+}
+
+int usbcan_chipregister(struct chipspecops_t *chipspecops)
+{
+       CANMSG("initializing usbcan chip operations\n");
+       chipspecops->chip_config=usbcan_chip_config;
+       chipspecops->baud_rate=usbcan_baud_rate;
+       chipspecops->standard_mask=usbcan_standard_mask;
+       chipspecops->extended_mask=usbcan_extended_mask;
+       chipspecops->message15_mask=usbcan_extended_mask;
+       chipspecops->clear_objects=usbcan_clear_objects;
+       chipspecops->config_irqs=usbcan_config_irqs;
+       chipspecops->pre_read_config=usbcan_pre_read_config;
+       chipspecops->pre_write_config=usbcan_pre_write_config;
+       chipspecops->send_msg=usbcan_send_msg;
+       chipspecops->check_tx_stat=usbcan_check_tx_stat;
+       chipspecops->wakeup_tx=usbcan_wakeup_tx;
+       chipspecops->remote_request=usbcan_remote_request;
+       chipspecops->enable_configuration=usbcan_enable_configuration;
+       chipspecops->disable_configuration=usbcan_disable_configuration;
+       chipspecops->attach_to_chip=usbcan_attach_to_chip;
+       chipspecops->release_chip=usbcan_release_chip;
+       chipspecops->set_btregs=usbcan_set_btregs;
+       chipspecops->start_chip=usbcan_start_chip;
+       chipspecops->stop_chip=usbcan_stop_chip;
+       chipspecops->irq_handler=usbcan_irq_handler;
+       chipspecops->irq_accept=NULL;
+       return 0;
+}
+
+/**
+ * usbcan_fill_chipspecops - fills chip specific operations
+ * @chip: pointer to chip representation structure
+ *
+ * The function fills chip specific operations for sja1000 (PeliCAN) chip.
+ *
+ * Return Value: returns negative number in the case of fail
+ */
+int usbcan_fill_chipspecops(struct canchip_t *chip)
+{
+       chip->chip_type="usbcan";
+       chip->max_objects=1;
+       usbcan_chipregister(chip->chipspecops);
+       return 0;
+}
+
+/**
+ * usbcan_init_chip_data - Initialize chips
+ * @candev: Pointer to candevice/board structure
+ * @chipnr: Number of the CAN chip on the hardware card
+ *
+ * The function usbcan_init_chip_data() is used to initialize the hardware
+ * structure containing information about the CAN chips.
+ * %CHIP_TYPE represents the type of CAN chip. %CHIP_TYPE can be "i82527" or
+ * "sja1000".
+ * The @chip_base_addr entry represents the start of the 'official' memory map
+ * of the installed chip. It's likely that this is the same as the @io_addr
+ * argument supplied at module loading time.
+ * The @clock entry holds the chip clock value in Hz.
+ * The entry @sja_cdr_reg holds hardware specific options for the Clock Divider
+ * register. Options defined in the %sja1000.h file:
+ * %sjaCDR_CLKOUT_MASK, %sjaCDR_CLK_OFF, %sjaCDR_RXINPEN, %sjaCDR_CBP, %sjaCDR_PELICAN
+ * The entry @sja_ocr_reg holds hardware specific options for the Output Control
+ * register. Options defined in the %sja1000.h file:
+ * %sjaOCR_MODE_BIPHASE, %sjaOCR_MODE_TEST, %sjaOCR_MODE_NORMAL, %sjaOCR_MODE_CLOCK,
+ * %sjaOCR_TX0_LH, %sjaOCR_TX1_ZZ.
+ * The entry @int_clk_reg holds hardware specific options for the Clock Out
+ * register. Options defined in the %i82527.h file:
+ * %iCLK_CD0, %iCLK_CD1, %iCLK_CD2, %iCLK_CD3, %iCLK_SL0, %iCLK_SL1.
+ * The entry @int_bus_reg holds hardware specific options for the Bus
+ * Configuration register. Options defined in the %i82527.h file:
+ * %iBUS_DR0, %iBUS_DR1, %iBUS_DT1, %iBUS_POL, %iBUS_CBY.
+ * The entry @int_cpu_reg holds hardware specific options for the cpu interface
+ * register. Options defined in the %i82527.h file:
+ * %iCPU_CEN, %iCPU_MUX, %iCPU_SLP, %iCPU_PWD, %iCPU_DMC, %iCPU_DSC, %iCPU_RST.
+ * Return Value: The function always returns zero
+ * File: src/usbcan.c
+ */
+int usbcan_init_chip_data(struct candevice_t *candev, int chipnr)
+{
+       struct canchip_t *chip=candev->chip[chipnr];
+
+       usbcan_fill_chipspecops(chip);
+
+       candev->chip[chipnr]->flags|=CHIP_IRQ_CUSTOM;
+       candev->chip[chipnr]->chip_base_addr=0;
+       candev->chip[chipnr]->clock = 0;
+
+       return 0;
+}
+
+
+/** *********************************
+ *    USB related functions
+ *  ********************************* */
+
+static int usbcan_sleep_thread(struct usbcan_usb *dev)
+{
+       int     rc = 0;
+
+       /* Wait until a signal arrives or we are woken up */
+       for (;;) {
+               try_to_freeze();
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (signal_pending(current)) {
+                       rc = -EINTR;
+                       break;
+               }
+               if (
+                       can_kthread_should_stop() ||
+                       test_bit(USBCAN_DATA_OK,&dev->flags) ||
+                       test_bit(USBCAN_TX_PENDING,&dev->flags) ||
+                       test_bit(USBCAN_TERMINATE,&dev->flags) ||
+                       test_bit(USBCAN_ERROR,&dev->flags)
+               )
+                       break;
+               schedule();
+       }
+       __set_current_state(TASK_RUNNING);
+       return rc;
+}
+
+static void usbcan_callback(struct urb *urb)
+{
+       struct usbcan_message *mess = urb->context;
+       int retval;
+
+       if (!test_bit(USBCAN_THREAD_RUNNING,&mess->dev->flags))
+               return;
+       if (test_bit(USBCAN_MESSAGE_TERMINATE,&mess->flags))
+               return;
+
+       switch (urb->status) {
+       case 0:
+               /* success */
+               CANMSG("%s > Message OK\n", __FUNCTION__);
+               set_bit(USBCAN_DATA_OK,&mess->dev->flags);
+               set_bit(USBCAN_MESSAGE_DATA_OK,&mess->flags);
+               if (test_bit(USBCAN_MESSAGE_TYPE_RX,&mess->flags)){
+                       CANMSG("%s > RX flag set\n", __FUNCTION__);
+                       set_bit(USBCAN_DATA_RX,&mess->dev->flags);
+               }
+               if (test_bit(USBCAN_MESSAGE_TYPE_TX,&mess->flags))
+                       CANMSG("%s > TX flag set\n", __FUNCTION__);
+                       set_bit(USBCAN_DATA_TX,&mess->dev->flags);
+               clear_bit(USBCAN_MESSAGE_URB_PENDING,&mess->flags);
+               if (test_bit(USBCAN_THREAD_RUNNING,&mess->dev->flags))
+                       wake_up_process(mess->dev->comthread);
+               else
+                       CANMSG("%s > USBCAN thread not running\n", __FUNCTION__);
+//                     wake_up(&mess->dev->queue);
+               return;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* this urb is terminated, clean up */
+               CANMSG("%s > Urb shutting down with status: %d\n", __FUNCTION__, urb->status);
+               set_bit(USBCAN_TERMINATE,&mess->dev->flags);
+               set_bit(USBCAN_MESSAGE_TERMINATE,&mess->flags);
+               clear_bit(USBCAN_MESSAGE_URB_PENDING,&mess->flags);
+               return;
+       default:
+               //CANMSG("%s > Nonzero status received: %d\n", __FUNCTION__, urb->status);
+               break;
+       }
+
+       // Try to send urb again on non significant errors
+       retval = usb_submit_urb (urb, GFP_ATOMIC);
+       if (retval<0){
+               CANMSG("%s > Retrying urb failed with result %d\n", __FUNCTION__, retval);
+               set_bit(USBCAN_ERROR,&mess->dev->flags);
+               clear_bit(USBCAN_MESSAGE_URB_PENDING,&mess->flags);
+               if (test_bit(USBCAN_THREAD_RUNNING,&mess->dev->flags))
+                       wake_up_process(mess->dev->comthread);
+//                     wake_up(&mess->dev->queue);
+       }
+}
+
+int usbcan_kthread(void *data)
+{
+       int i,retval=0;
+       struct usbcan_usb *dev=(struct usbcan_usb *)data;
+       struct msgobj_t *obj;
+
+  CANMSG("Usbcan thread started...\n");
+
+       if (!dev->chip)
+               goto error;
+       obj=dev->chip->msgobj[0];
+
+       /* Prepare receive urbs  */
+       for (i=0;i<USBCAN_TOT_RX_URBS;i++){
+               dev->rx[i].u = usb_alloc_urb(0, GFP_KERNEL);
+               if (!dev->rx[i].u){
+                       CANMSG("Error allocating %d. usb receive urb\n",i);
+                       goto error;
+               }
+               dev->rx[i].u->dev = dev->udev;
+               dev->rx[i].dev = dev;
+               usb_fill_bulk_urb(dev->rx[i].u, dev->udev,
+                               usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
+                               dev->rx[i].msg, USBCAN_TRANSFER_SIZE,
+                               usbcan_callback, &dev->rx[i]);
+               set_bit(USBCAN_MESSAGE_TYPE_RX,&dev->rx[i].flags);
+       }
+
+       /* Prepare transmit urbs  */
+       for (i=0;i<USBCAN_TOT_TX_URBS;i++){
+               dev->tx[i].u = usb_alloc_urb(0, GFP_KERNEL);
+               if (!dev->tx[i].u){
+                       CANMSG("Error allocating %d. usb transmit urb\n",i);
+                       goto error;
+               }
+               dev->tx[i].u->dev = dev->udev;
+               dev->tx[i].dev = dev;
+               usb_fill_bulk_urb(dev->tx[i].u, dev->udev,
+                               usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
+                               dev->tx[i].msg, USBCAN_TRANSFER_SIZE,
+                               usbcan_callback, &dev->tx[i]);
+               set_bit(USBCAN_MESSAGE_FREE,&dev->tx[i].flags);
+               set_bit(USBCAN_MESSAGE_TYPE_TX,&dev->tx[i].flags);
+       }
+
+       set_bit(USBCAN_THREAD_RUNNING,&dev->flags);
+       set_bit(USBCAN_FREE_TX_URB,&dev->flags);
+
+       for (i=0;i<USBCAN_TOT_RX_URBS;i++){
+               retval=usb_submit_urb(dev->rx[i].u, GFP_KERNEL);
+               if (retval){
+                       CANMSG("%d. URB error %d\n",i,retval);
+                       set_bit(USBCAN_ERROR,&dev->flags);
+                       goto exit;
+               }
+               else
+                       set_bit(USBCAN_MESSAGE_URB_PENDING,&dev->rx[i].flags);
+       }
+  /* an endless loop in which we are doing our work */
+  for(;;)
+  {
+               /* We need to do a memory barrier here to be sure that
+               the flags are visible on all CPUs. */
+               mb();
+               /* fall asleep */
+               if (!(can_kthread_should_stop() || test_bit(USBCAN_TERMINATE,&dev->flags))){
+                       if (usbcan_sleep_thread(dev)<0)
+                               break;
+/*                     wait_event_interruptible(dev->queue,
+                               can_kthread_should_stop() ||
+                               test_bit(USBCAN_DATA_OK,&dev->flags) ||
+                               test_bit(USBCAN_TX_PENDING,&dev->flags) ||
+                               test_bit(USBCAN_TERMINATE,&dev->flags) ||
+                               test_bit(USBCAN_ERROR,&dev->flags)
+                       );*/
+               }
+               /* We need to do a memory barrier here to be sure that
+               the flags are visible on all CPUs. */
+               mb();
+
+               /* here we are back from sleep because we caught a signal. */
+               if (can_kthread_should_stop()){
+                       /* we received a request to terminate ourself */
+                       break;
+               }
+
+               /* here we are back from sleep because we caught a signal. */
+               if (test_bit(USBCAN_TERMINATE,&dev->flags)){
+                       /* we received a request to terminate ourself */
+                       break;
+               }
+
+               { /* Normal work to do */
+                       if (test_and_clear_bit(USBCAN_DATA_OK,&dev->flags)){
+                               CANMSG("USBCAN Succesfull data transfer\n");
+
+                               if (test_and_clear_bit(USBCAN_DATA_RX,&dev->flags)){
+                                       usbcan_kthread_read_handler(dev, obj);
+                               }
+                               if (test_and_clear_bit(USBCAN_DATA_TX,&dev->flags)){
+                                       usbcan_kthread_write_handler(dev, obj);
+                               }
+                       }
+                       if (test_and_clear_bit(USBCAN_TX_PENDING,&dev->flags)){
+                               usbcan_kthread_write_request_handler(dev, obj);
+                       }
+    }
+  }
+       set_bit(USBCAN_TERMINATE,&dev->flags);
+exit:
+  /* here we go only in case of termination of the thread */
+       for (i=0;i<USBCAN_TOT_RX_URBS;i++){
+               if (dev->rx[i].u){
+                       set_bit(USBCAN_MESSAGE_TERMINATE,&dev->rx[i].flags);
+                       usb_kill_urb(dev->rx[i].u);
+                       usb_free_urb(dev->rx[i].u);
+               }
+       }
+       for (i=0;i<USBCAN_TOT_TX_URBS;i++){
+               if (dev->tx[i].u){
+                       set_bit(USBCAN_MESSAGE_TERMINATE,&dev->tx[i].flags);
+                       usb_kill_urb(dev->tx[i].u);
+                       usb_free_urb(dev->tx[i].u);
+               }
+       }
+       clear_bit(USBCAN_THREAD_RUNNING,&dev->flags);
+
+  CANMSG ("usbcan thread finished!\n");
+  return 0;
+error:
+  /* cleanup the thread, leave */
+  CANMSG ("kernel thread terminated!\n");
+  return -ENOMEM;
+}
+
+static int usbcan_probe(struct usb_interface *interface, const struct usb_device_id *id)
+{
+       struct usbcan_devs *usbdevs=NULL;
+       struct usb_host_interface *iface_desc;
+       struct usb_endpoint_descriptor *endpoint;
+       size_t buffer_size;
+       int i,j,k;
+       int retval = -ENOMEM;
+
+       iface_desc = interface->cur_altsetting;
+       if (iface_desc->desc.bNumEndpoints % 2){
+               CANMSG("Endpoint count must be even");
+               goto noalloc;
+       }
+
+       usbcan_chip_count = iface_desc->desc.bNumEndpoints / 2;
+
+       usbdevs = (struct usbcan_devs *) can_checked_malloc(sizeof(struct usbcan_devs));
+       if (!usbdevs) {
+               CANMSG("Out of memory");
+               goto error;
+       }
+       memset(usbdevs, 0, sizeof(struct usbcan_devs));
+
+       usbdevs->count=usbcan_chip_count;
+
+       usbdevs->devs = (struct usbcan_usb **) can_checked_malloc(usbcan_chip_count * sizeof(struct usbcan_usb *));
+       if (!usbdevs->devs) {
+               CANMSG("Out of memory");
+               goto error;
+       }
+       memset(usbdevs->devs, 0, usbcan_chip_count * sizeof(struct usbcan_usb *));
+
+       for (j=0;j<usbcan_chip_count;j++){
+               struct usbcan_usb *dev;
+               int epnum=-1,was;
+
+               /* allocate memory for our device state and initialize it */
+               usbdevs->devs[j] = (struct usbcan_usb *) can_checked_malloc(sizeof(struct usbcan_usb));
+               if (!usbdevs->devs[j]) {
+                       CANMSG("Out of memory");
+                       goto error;
+               }
+               memset(usbdevs->devs[j], 0, sizeof(struct usbcan_usb));
+               dev=usbdevs->devs[j];
+
+               mutex_init(&dev->io_mutex);
+               init_waitqueue_head(&dev->queue);
+               dev->udev = interface_to_usbdev(interface);
+               dev->interface = interface;
+
+               /* set up the endpoint information */
+               for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+                       endpoint = &iface_desc->endpoint[i].desc;
+
+                       if (epnum==-1){
+                               was=0;
+                               for (k=0;k<j;k++){
+                                       if ((usbdevs->devs[k]->bulk_in_endpointAddr & USB_ENDPOINT_NUMBER_MASK) == (endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK))
+                                               was=1;
+                               }
+                               if (was) continue;
+                               epnum=endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+                       }
+
+                       if (!dev->bulk_in_endpointAddr &&
+                                       usb_endpoint_is_bulk_in(endpoint)) {
+                               if (epnum == (endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)){
+                                       /* we found a bulk in endpoint */
+                                       buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+                                       dev->bulk_in_size = buffer_size;
+                                       dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
+                                       dev->bulk_in_buffer = can_checked_malloc(buffer_size);
+                                       if (!dev->bulk_in_buffer) {
+                                               CANMSG("Could not allocate bulk_in_buffer");
+                                               goto error;
+                                       }
+                               }
+                       }
+
+                       if (!dev->bulk_out_endpointAddr &&
+                                       usb_endpoint_is_bulk_out(endpoint)) {
+                               if (epnum == (endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)){
+                               /* we found a bulk out endpoint */
+                                       dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
+                               }
+                       }
+
+               }
+               if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) {
+                       CANMSG("Could not find all bulk-in and bulk-out endpoints for chip %d",j);
+                       goto error;
+               }
+       }
+       /* save our data pointer in this interface device */
+       usb_set_intfdata(interface, usbdevs);
+
+       if (!(usbdevs->candev=register_usbdev("usbcan",(void *) usbdevs, usbcan_register_devs)))
+               goto register_error;
+
+       /* let the user know what node this device is now attached to */
+       CANMSG("USBCAN device now attached\n");
+       return 0;
+
+register_error:
+       cleanup_usbdev(usbdevs->candev);
+error:
+       if (usbdevs){
+               if (usbdevs->devs){
+                       if (usbdevs->devs[0]){
+                               usb_put_dev(usbdevs->devs[0]->udev);
+                       }
+                       for (j=0;j<usbdevs->count;j++){
+                               if (!usbdevs->devs[j])  continue;
+
+                               if (usbdevs->devs[j]->bulk_in_buffer)
+                                       can_checked_free(usbdevs->devs[j]->bulk_in_buffer);
+                               if (usbdevs->devs[j]->chip){
+                                       usbdevs->devs[j]->chip->chip_data=NULL;
+                               }
+                               can_checked_free(usbdevs->devs[j]);
+                       }
+                       can_checked_free(usbdevs->devs);
+               }
+               can_checked_free(usbdevs);
+       }
+noalloc:
+       return retval;
+}
+
+// Physically disconnected device
+static void usbcan_disconnect(struct usb_interface *interface)
+{
+       struct usbcan_devs *usbdevs;
+       int j;
+       usbdevs = usb_get_intfdata(interface);
+       if (usbdevs==NULL){
+               CANMSG("USBCAN device seems to be removed\n");
+               return;
+       }
+       usb_set_intfdata(interface, NULL);
+
+       if (usbdevs->devs){
+               usb_put_dev((*usbdevs->devs)->udev);
+       }
+       cleanup_usbdev(usbdevs->candev);
+       if (usbdevs->devs){
+               for (j=0;j<usbdevs->count;j++){
+                       if (!usbdevs->devs[j])  continue;
+
+                       /* prevent more I/O from starting */
+                       mutex_lock(&usbdevs->devs[j]->io_mutex);
+                       usbdevs->devs[j]->interface = NULL;
+                       mutex_unlock(&usbdevs->devs[j]->io_mutex);
+
+                       while (test_bit(USBCAN_THREAD_RUNNING,&usbdevs->devs[j]->flags))
+                       {
+                               CANMSG("USBCAN thread has not stopped, trying to wake...\n");
+                               set_bit(USBCAN_TERMINATE,&usbdevs->devs[j]->flags);
+                               wake_up_process(usbdevs->devs[j]->comthread);
+                               schedule();
+//                     can_kthread_stop(dev->comthread);
+                       }
+
+                       if (usbdevs->devs[j]->bulk_in_buffer)
+                               can_checked_free(usbdevs->devs[j]->bulk_in_buffer);
+                       // if (usbdevs->devs[j]->chip){
+                       //      usbdevs->devs[j]->chip->chip_data=NULL;
+                       // }
+                       can_checked_free(usbdevs->devs[j]);
+                       usbdevs->devs[j]=NULL;
+               }
+               can_checked_free(usbdevs->devs);
+       }
+       can_checked_free(usbdevs);
+
+       CANMSG("USBCAN now disconnected\n");
+}
+
+int usbcan_init(void){
+       return usb_register(&usbcan_driver);
+}
+
+void usbcan_exit(void){
+       usb_deregister(&usbcan_driver);
+}
diff --git a/omk/rules/sysless/Makefile.rules b/omk/rules/sysless/Makefile.rules
new file mode 100644 (file)
index 0000000..e444ab3
--- /dev/null
@@ -0,0 +1,1010 @@
+#                   Version for system-less builds.          #OMK@sysless
+#
+#  Makefile.rules - OCERA make framework common project rules -*- makefile -*- #OMK@base
+#
+#  (C) Copyright 2003 by Pavel Pisa - OCERA team member
+#  (C) Copyright 2006 by Michal Sojka - Czech Technical University, FEE, DCE
+#
+#  Homepage: http://rtime.felk.cvut.cz/omk/
+#
+# The OMK build system is distributed under the GNU General Public
+# License.  See file COPYING for details.
+#
+# input variables
+# V                .. if set to 1, full command text is shown else short form is used
+# W                .. whole tree - if set to 1, make is always called from the top-level directory
+# SUBDIRS          .. list of subdirectories intended for make from actual directory
+# default_CONFIG   .. list of default config assignments CONFIG_XXX=y/n ...
+# LN_HEADERS       .. if "y", header files are symbolicaly linked instead of copied. #OMK@include
+#                                                            #OMK@sysless
+# bin_PROGRAMS     .. list of the require binary programs
+# test_PROGRAMS    .. list of the test programs
+# include_HEADERS  .. list of the user-space public header files
+# lib_LIBRARIES    .. list of the user-space libraries
+# lib_LDSCRIPTS    .. list of LD scripts that should be copied to the lib direcotry
+# lib_obj_SOURCES  .. list of source files which should be compiled and
+#                    the produced object file placed to the lib directory (e.g. crt0.S)
+# shared_LIBRARIES .. list of the user-space shared libraries
+# nobase_include_HEADERS .. public headers copied even with directory part
+# renamed_include_HEADERS .. public headers copied to the different target name (xxx.h->yyy.h)
+# utils_PROGRAMS   .. list of the development utility programs (compiled for host computer, this might change in future)
+# xxx_SOURCES      .. list of specific target sources
+# xxx_LIBS         .. list of specific target libraries
+# INCLUDES         .. additional include directories and defines for user-space
+# lib_LOADLIBES    .. list of libraries linked to each executable
+# link_VARIANTS    .. list of ld script suffixes (after hypen `-') that
+#                     should be used for linking (e.g. ram flash). If this is not
+#                    specified, then the value of DEFAULT_LD_SCRIPT_VARIANT from config.target is used.
+# PREFIX_DIR       .. Prefix to  directories in _compiled and _build. Used in config.omk.
+# LOCAL_CONFIG_H   .. name of local config.h file generated from values #OMK@config_h
+#                     of options defined in the current directory
+# config_include_HEADERS .. names of global config files (possibly
+#                     with subdirectories)
+# xxx_DEFINES      .. list of config directives to be included in
+#                     config header file of the name <somedir>/xxx.h
+# DOXYGEN          .. if non-empty, generated headers includes Doxygen's @file
+#                    command, so it is possible to document config
+#                    variables.
+# local_EVALUATE   .. Makefile hook, which is executed at the end of #OMK@localeval
+#                     the Makefile.rules. Used only for dirty hacks.
+OMK_RULES_TYPE=sysless                                       #OMK@__type
+                                                             #OMK@base
+# We need to ensure definition of sources directory first
+ifndef SOURCES_DIR
+# Only shell built-in pwd understands -L
+SOURCES_DIR := $(shell ( pwd -L ) )
+endif
+
+# If we are not called by OMK leaf Makefile...
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(abspath $(dir $(filter %Makefile.rules,$(MAKEFILE_LIST))))
+endif
+
+# OUTPUT_DIR is the place where _compiled, _build and possible other
+# files/directories are created. By default is the same as
+# $(MAKERULES_DIR).
+ifndef OUTPUT_DIR
+OUTPUT_DIR := $(MAKERULES_DIR)
+endif
+
+.PHONY: all default check-make-ver omkize
+
+ifdef W
+  ifeq ("$(origin W)", "command line")
+    OMK_WHOLE_TREE:=$(W)
+  endif
+endif
+ifndef OMK_WHOLE_TREE
+  OMK_WHOLE_TREE:=0
+endif
+
+ifneq ($(OMK_WHOLE_TREE),1)
+all: check-make-ver default
+       @echo "Compilation finished"
+else
+# Run make in the top-level directory
+all:
+       @$(MAKE) -C $(MAKERULES_DIR) OMK_SERIALIZE_INCLUDED=n SOURCES_DIR=$(MAKERULES_DIR) RELATIVE_DIR="" $(MAKECMDGOALS) W=0
+endif
+
+ifdef OMK_TESTSROOT
+# Usage: $(call canttest,<error message>)
+define canttest
+       ( echo "$(1)" > $(OUTPUT_DIR)/_canttest; echo "$(1)"; exit 1 )
+endef
+else
+define canttest
+       echo "$(1)"
+endef
+endif
+
+#=========================
+# Include the config file
+
+# FIXME: I think CONFIG_FILE_OK variable is useless. We have three
+# config files and it is not clearly defined to which file is this
+# variable related.
+ifneq ($(CONFIG_FILE_OK),y)
+ifndef CONFIG_FILE
+CONFIG_FILE      := $(OUTPUT_DIR)/config.omk
+endif
+ifneq ($(wildcard $(CONFIG_FILE)-default),)
+-include $(CONFIG_FILE)-default
+else
+ifneq ($(MAKECMDGOALS),default-config)
+$(warning Please, run "make default-config" first)
+endif
+endif
+
+-include $(OUTPUT_DIR)/config.target
+
+ifneq ($(wildcard $(CONFIG_FILE)),)
+-include $(CONFIG_FILE)
+CONFIG_FILE_OK = y
+endif
+endif #$(CONFIG_FILE_OK)
+
+
+CONFIG_FILES ?= $(wildcard $(CONFIG_FILE)-default) $(wildcard $(OUTPUT_DIR)/config.target) $(wildcard $(CONFIG_FILE))
+
+
+export SOURCES_DIR MAKERULES_DIR RELATIVE_DIR
+export CONFIG_FILE CONFIG_FILES OMK_SERIALIZE_INCLUDED OMK_VERBOSE OMK_SILENT
+# OMK_SERIALIZE_INCLUDED has to be exported to submakes because passes
+# must to be serialized only in the toplevel make.
+
+ifndef RELATIVE_DIR
+RELATIVE_DIR := $(SOURCES_DIR:$(OUTPUT_DIR)%=%)
+endif
+#$(warning  === RELATIVE_DIR = "$(RELATIVE_DIR)" ===)
+override RELATIVE_DIR := $(RELATIVE_DIR:/%=%)
+override RELATIVE_DIR := $(RELATIVE_DIR:\\%=%)
+#$(warning  RELATIVE_DIR = "$(RELATIVE_DIR)")
+override BACK2TOP_DIR := $(shell echo $(RELATIVE_DIR)/ | sed -e 's_//_/_g' -e 's_/\./_/_g' -e 's_^\./__g'  -e 's_\([^/][^/]*\)_.._g' -e 's_/$$__')
+#$(warning  BACK2TOP_DIR = "$(BACK2TOP_DIR)")
+
+#$(warning SOURCES_DIR = "$(SOURCES_DIR)")
+#$(warning MAKERULES_DIR = "$(OUTPUT_DIR)")
+#$(warning RELATIVE_DIR = "$(RELATIVE_DIR)")
+
+# We have to use RELATIVE_PREFIX because of mingw
+override RELATIVE_PREFIX := $(RELATIVE_DIR)/
+override RELATIVE_PREFIX := $(RELATIVE_PREFIX:/%=%)
+
+#vpath %.c $(SOURCES_DIR)
+#vpath %.cc $(SOURCES_DIR)
+#vpath %.cxx $(SOURCES_DIR)
+
+# Define srcdir for Automake compatibility
+srcdir = $(SOURCES_DIR)
+
+# Defines for quiet compilation
+ifdef V
+  ifeq ("$(origin V)", "command line")
+    OMK_VERBOSE = $(V)
+  endif
+endif
+ifndef OMK_VERBOSE
+  OMK_VERBOSE = 0
+endif
+ifneq ($(OMK_VERBOSE),0)
+  Q =
+else
+  Q = @
+endif
+ifneq ($(findstring s,$(MAKEFLAGS)),)
+  QUIET_CMD_ECHO = true
+  OMK_SILENT = 1
+else
+  QUIET_CMD_ECHO = echo
+endif
+
+MAKEFILE_OMK=Makefile.omk
+# All subdirectories (even linked ones) containing Makefile.omk
+# Usage in Makefile.omk: SUBDIRS = $(ALL_OMK_SUBDIRS)
+ALL_OMK_SUBDIRS = $(patsubst %/$(MAKEFILE_OMK),%,$(patsubst $(SOURCES_DIR)/%,%,$(wildcard $(SOURCES_DIR)/*/$(MAKEFILE_OMK))))
+
+# ===================================================================
+# We have set up all important variables, so we can check and include
+# real OCERA style Makefile.omk now
+ifndef OMK_INCLUDED
+include $(SOURCES_DIR)/$(MAKEFILE_OMK)
+ifeq ($(AUTOMATIC_SUBDIRS),y)
+SUBDIRS?=$(ALL_OMK_SUBDIRS)
+endif
+OMK_INCLUDED := 1
+endif
+
+check-make-ver:
+       @GOOD_MAKE_VERSION=`echo $(MAKE_VERSION) | sed -n -e 's/^[4-9]\..*\|^3\.9[0-9].*\|^3\.8[1-9].*/y/p'` ; \
+       if [ x$$GOOD_MAKE_VERSION != xy ] ; then \
+               echo "Your make program version is too old and does not support OMK system." ; \
+               echo "Please update to make program 3.81beta1 or newer." ; exit 1 ; \
+       fi
+
+distclean dist-clean:
+       @$(QUIET_CMD_ECHO) "  RM      $(COMPILED_DIR_NAME) $(BUILD_DIR_NAME)"
+       @rm -fr $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)  $(OUTPUT_DIR)/$(BUILD_DIR_NAME)
+
+# Common OMK templates
+# ====================
+
+# Syntax: $(call mkdir,<dir name>)
+define mkdir_def
+       [ -d $(1) ] || mkdir -p $(1) || exit 1
+endef
+
+ifneq ($(OMK_VERBOSE),2)
+NO_PRINT_DIRECTORY := --no-print-directory
+endif
+
+ifeq ($(USE_LEAF_MAKEFILES),n)
+export USE_LEAF_MAKEFILES
+SUBDIR_MAKEFILE=$(MAKERULES_DIR)/Makefile.rules
+SOURCESDIR_MAKEFILE=$(MAKERULES_DIR)/Makefile.rules
+else
+SUBDIR_MAKEFILE=$(SOURCES_DIR)/$(3)/Makefile
+SOURCESDIR_MAKEFILE=$(SOURCES_DIR)/Makefile
+endif
+
+pass = $(strip $(1))
+
+# Call a pass in a subdirectory
+# Usage: $(call omk_pass_subdir_template,<pass name>,<build dir>,<subdir>)
+define omk_pass_subdir_template
+.PHONY: $(pass)-$(3)-subdir
+$(pass)-submakes: $(pass)-$(3)-subdir
+$(pass)-$(3)-subdir:
+       @$(call mkdir_def,$(2)/$(3))
+       +@$(MAKE) SOURCES_DIR=$(SOURCES_DIR)/$(3) $(NO_PRINT_DIRECTORY) \
+               RELATIVE_DIR=$(RELATIVE_PREFIX)$(3) -C $(2)/$(3) \
+               -f $(SUBDIR_MAKEFILE) $(pass)-submakes
+# In subdirectories we can call submakes directly since passes are
+# already searialized on the toplevel make.
+endef
+
+ifdef OMK_TESTSROOT
+check-target = $(1:%=%-check)
+endif
+
+# Call a pass in a subdirectory
+# Usage: $(call extra_rules_subdir_template,<subdir>)
+define extra_rules_subdir_template
+extra-rules-subdirs: extra-rules-$(1)
+extra-rules-$(1):
+       +@$(MAKE) OMK_SERIALIZE_INCLUDED=n MAKERULES_DIR=$(SOURCES_DIR)/$(1) OUTPUT_DIR=$(OUTPUT_DIR) \
+               SOURCES_DIR=$(SOURCES_DIR)/$(1) RELATIVE_DIR=$(RELATIVE_PREFIX)$(1) -C $(SOURCES_DIR)/$(1)
+endef
+
+.PHONY: extra-rules-subdirs
+extra-rules-subdirs:
+
+$(foreach subdir,$(EXTRA_RULES_SUBDIRS),$(eval $(call extra_rules_subdir_template,$(subdir))))
+
+# Usage: $(call omk_pass_template,<pass name>,<build dir>,[<local make flags>],[<local enable condition>])
+define omk_pass_template
+.PHONY: $(pass) $(pass)-local $(pass)-check $(pass)-submakes
+$(foreach subdir,$(SUBDIRS),$(eval $(call omk_pass_subdir_template,$(pass),$(2),$(subdir))))
+$(pass):
+# Submakes have to be called this way and not as dependecies for pass
+# serialization to work
+       +@$(MAKE) SOURCES_DIR=$(SOURCES_DIR) $(NO_PRINT_DIRECTORY) \
+               RELATIVE_DIR=$(RELATIVE_DIR) \
+               -f $(SOURCESDIR_MAKEFILE) $(pass)-submakes
+$(pass)-submakes:
+       @true                   # Do not emit "nothing to be done" messages
+
+ifneq ($(4)$($(pass)_HOOKS),)
+$(pass)-submakes: $(pass)-this-dir
+$(pass)-this-dir: $(foreach subdir,$(SUBDIRS),$(pass)-$(subdir)-subdir)
+       +@echo "make[omk]: $(pass) in $(RELATIVE_DIR)"
+       @$(call mkdir_def,$(2))
+       +@$(MAKE) $(NO_PRINT_DIRECTORY) SOURCES_DIR=$(SOURCES_DIR) RELATIVE_DIR=$(RELATIVE_DIR) -C $(2) \
+               -f $(SOURCESDIR_MAKEFILE) $(3) $(check-target) $(1:%=%-local)
+$(pass)-local: $($(pass)_HOOKS)
+endif
+endef
+
+# =======================
+# DEFAULT CONFIG PASS
+
+default-config:
+       @echo "# Start of OMK config file" > "$(CONFIG_FILE)-default"
+       @echo "# This file should not be altered manually" >> "$(CONFIG_FILE)-default"
+       @echo "# Overrides should be stored in file $(notdir $(CONFIG_FILE))" >> "$(CONFIG_FILE)-default"
+       @echo >> "$(CONFIG_FILE)-default"
+       @$(MAKE) $(NO_PRINT_DIRECTORY) -C $(OUTPUT_DIR) \
+               RELATIVE_DIR="" SOURCES_DIR=$(OUTPUT_DIR) \
+               -f $(OUTPUT_DIR)/Makefile default-config-pass
+
+$(eval $(call omk_pass_template,default-config-pass,$$(LOCAL_BUILD_DIR),,always))
+
+default-config-pass-local:
+#      @echo Default config for $(RELATIVE_DIR)
+       @echo "# Config for $(RELATIVE_DIR)" >> "$(CONFIG_FILE)-default"
+       @$(foreach x, $(default_CONFIG), echo '$(x)' | \
+               sed -e 's/^[^=]*=x$$/#\0/' >> "$(CONFIG_FILE)-default" ; )
+
+
+omkize:
+       $(Q)if ! grep -q MAKERULES_DIR Makefile; then \
+          echo "Makefile is not OMK leaf makefile!" >&2; exit 1; \
+       fi
+       $(Q)for i in `find -L . -name Makefile.omk` ; do \
+          d=`dirname $${i}`; \
+          if ! test -f "$${d}/Makefile.rules" && ( ! test -f "$${d}/Makefile" || ! cmp --silent Makefile "$${d}/Makefile" ); then \
+             rm -f "$${d}/Makefile"; \
+             cp -v Makefile "$${d}/Makefile"; \
+          fi \
+       done
+                                                             #OMK@gcc
+# Rules for compilation of C, C++ and assembler sources using GNU
+# toolchain.
+
+# Interface to other rules:
+
+# Input variables:
+# LIB_DIR - directory where compiled libraries are stored
+# OBJS_DIR - directory where intermediate files (.o, .map, ...) are stored
+# INCLUDE_DIR - where includes can be found
+# from config.omk or Makefile.omk
+# CROSS_COMPILE - 
+# TARGET_ARCH, DEBUG, OPTIMIZE, DEFS - forms CFLAGS
+# from base: SOURCES_DIR
+# from Makefile.omk: lib_LOADLIBES
+
+# Output variables:
+# SOURCES - all the source files that needs to be compiled (except for shared library sources)
+# SOLIB_SOURCES - all the source files that needs to be compiled for a shared library
+# OBJ_EXT - extension of object files
+# LIB_EXT - extension of library files
+# LIB_PREF - prefix for library files
+# ASM_EXT - extension of assembler sources
+
+# Templates:
+# COMPILER_DEFS_template - definitions that should be defined before
+# the following templates can be used. The input variables needs to be
+# defined before evaluating this template
+
+# COMPILE_c_o_template, COMPILE_cc_o_template, COMPILE_S_o_template -
+# templates that create rules for compilation of sources
+
+# CMETRIC_o_h_template - FIXME
+
+# PROGRAM_template, LIBRARY_template, SOLIB_template - templates that
+# create rules for compilation of a program, library and shared
+# library. The rules can use rules produced by COMPILE_xxx_template.
+
+define COMPILER_DEFS_template
+OBJ_EXT = .o
+LIB_EXT = .a
+LIB_PREF = lib
+ASM_EXT = .S
+
+CC = $(CROSS_COMPILE)gcc
+LINK = $(CROSS_COMPILE)ld
+AR = $(CROSS_COMPILE)ar
+OBJCOPY = $(CROSS_COMPILE)objcopy
+NM = $(CROSS_COMPILE)nm
+
+CFLAGS += $(TARGET_ARCH) $(DEBUG) $(OPTIMIZE)
+CFLAGS += -Wall
+CFLAGS += -I$(SOURCES_DIR)
+CFLAGS += -I$(INCLUDE_DIR)
+
+LOADLIBES += -L$(LIB_DIR)
+LOADLIBES += $(lib_LOADLIBES:%=-l%)
+
+
+-include $(OBJS_DIR)/*.d
+
+#%.lo: %.c
+#      $(CC) -o $@ $(LCFLAGS) -c $<
+
+c_o_COMPILE = $$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $$(CFLAGS)
+
+cc_o_COMPILE = $$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $$(CFLAGS)
+
+S_o_COMPILE = $$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+       $(CPPFLAGS) $(AM_CFLAGS) $$(CFLAGS) $(ASFLAGS)
+
+
+# Check GCC version for user build
+ifndef CC_MAJOR_VERSION
+CC_MAJOR_VERSION = $$(shell $$(CC) -dumpversion | sed -e 's/\([^.]\)\..*/\1/')
+endif
+# Prepare suitable define for dependency building
+ifeq ($$(CC_MAJOR_VERSION),2)
+CC_DEPFLAGS = -Wp,-MD,"$$@.d.tmp"
+else
+CC_DEPFLAGS = -MT $$@ -MD -MP -MF "$$@.d.tmp"
+endif
+
+endef # COMPILER_DEFS_template
+
+
+# Syntax: $(call COMPILE_c_o_template,<source>,<target>,<additional c-flags>)
+define COMPILE_c_o_template
+$(2): $(1) $$(GEN_HEADERS)
+       @$(QUIET_CMD_ECHO) "  CC      $$@"
+       $(Q) if $$(c_o_COMPILE) $$(CC_DEPFLAGS) $(3) -o $$@ -c $$< ; \
+       then mv -f "$$@.d.tmp" "$$@.d" ; \
+       else rm -f "$$@.d.tmp" ; exit 1; \
+       fi
+endef
+
+
+
+# Syntax: $(call COMPILE_cc_o_template,<source>,<target>,<additional c-flags>)
+define COMPILE_cc_o_template
+$(2): $(1) $$(GEN_HEADERS)
+       @$(QUIET_CMD_ECHO) "  CXX     $$@"
+       $(Q) if $$(cc_o_COMPILE) $$(CC_DEPFLAGS) $(3) -o $$@ -c $$< ; \
+       then mv -f "$$@.d.tmp" "$$@.d" ; \
+       else rm -f "$$@.d.tmp" ; exit 1; \
+       fi
+endef
+
+# Syntax: $(call COMPILE_S_o_template,<source>,<target>,<additional c-flags>)
+define COMPILE_S_o_template
+$(2): $(1) $$(GEN_HEADERS)
+       @$(QUIET_CMD_ECHO) "  AS      $$@"
+       $(Q) if $$(S_o_COMPILE) -D__ASSEMBLY__ $$(CC_DEPFLAGS) $(3) -o $$@ -c $$< ; \
+       then if [ -e "$$@.d.tmp" ] ; then mv -f "$$@.d.tmp" "$$@.d" ; fi ; \
+       else rm -f "$$@.d.tmp" ; exit 1; \
+       fi
+endef
+
+# Syntax: $(call CMETRIC_o_h_template,<object_file>,<target_header>)
+define CMETRIC_o_h_template
+$(2): $(1)
+       @$(QUIET_CMD_ECHO) "  CMETRIC $$@"
+       $(Q)if [ -n `dirname $$@` ] ; then \
+             if [ ! -e `dirname $$@` ] ; then \
+               mkdir -p `dirname $$@` ; fi ; fi
+       $(Q)echo >$$@ '/* Automatically generated from $$< */'
+       $(Q)echo >>$$@ '/* Conditionals to control compilation */'
+       $(Q)set -o pipefail ; $(NM) $$< \
+               | sed -n 's/^ *0*\(0[0-9A-Fa-f]*\) *A *_cmetric2cond_\([A-Za-z_0-9]*\) */#define \2 0x\1/p' \
+               | sort >>$$@
+       $(Q)echo >>$$@ '/* Defines from the values defined to symbols */'
+       $(Q)set -o pipefail ; $(NM) $$< \
+               | sed -n 's/^ *0*\(0[0-9A-Fa-f]*\) *A *_cmetric2def_\([A-Za-z_0-9]*\) */#define \2 0x\1/p' \
+               | sort >>$$@
+endef
+
+# Syntax: $(call PROGRAM_template,<executable-name>,<dir>,<link-variant>)
+define PROGRAM_template
+$(1)_OBJS += $$(filter %.o,$$($(1)_SOURCES:%.c=%.o))
+$(1)_OBJS += $$(filter %.o,$$($(1)_SOURCES:%.cc=%.o))
+$(1)_OBJS += $$(filter %.o,$$($(1)_SOURCES:%.cxx=%.o))
+$(1)_OBJS += $$(filter %.o,$$($(1)_SOURCES:%.S=%.o))
+$(1)_OBJS += $$(filter %.o,$(1)_SOURCES)
+$(1)_OBJS := $$(sort $$($(1)_OBJS))
+
+SOURCES += $$($(1)_SOURCES)
+
+ifneq ($(LD_SCRIPT),)
+$(1)$(3:%=-%)_LDFLAGS = -Wl,-T,$(LD_SCRIPT).ld$(3:%=-%)
+endif
+
+$(2)/$(1)$(3:%=-%): $$($(1)_OBJS)
+       @$(QUIET_CMD_ECHO) "  LINK    $$@"
+       $(Q) $$(shell if [ -z "$$(filter %.cc,$$($(1)_SOURCES))" ] ; \
+         then echo $$(CC)  $$(CPPFLAGS) $$(AM_CPPFLAGS) $$(AM_CFLAGS)   $$(CFLAGS) ; \
+         else echo $$(CXX) $$(CPPFLAGS) $$(AM_CPPFLAGS) $$(AM_CXXFLAGS) $$(CXXFLAGS) ; fi) \
+         $$(AM_LDFLAGS) $$(LDFLAGS) $$($(1)$(3:%=-%)_LDFLAGS) -Wl,-Map,$(1)$(3:%=-%).map \
+         $$($(1)_OBJS) $$(LOADLIBES) $$($(1)_MOREOBJS) $$($(1)_LIBS:%=-l%) \
+         -o $$@
+       @echo "$(2)/$(1)$(3:%=-%): \\" >$(OBJS_DIR)/$(1)$(3:%=-%).exe.d
+       @if [ -n "$(LD_SCRIPT)" ]; then \
+         echo "  $(LIB_DIR)/$(LD_SCRIPT).ld$(3:%=-%) \\" >>$(OBJS_DIR)/$(1)$(3:%=-%).exe.d; fi
+       @sed -n -e 's|^LOAD \(.*\)$$$$|  \1  \&|p' $(OBJS_DIR)/$(1)$(3:%=-%).map|tr '&' '\134'  >>$(OBJS_DIR)/$(1)$(3:%=-%).exe.d
+       @echo >>$(OBJS_DIR)/$(1).exe.d
+endef
+
+# Rules for other output formats (can be specified by OUTPUT_FORMATS)
+%.bin: %
+       @$(QUIET_CMD_ECHO) "  OBJCOPY $@"
+       $(Q) $(OBJCOPY)  --output-target=binary -S $< $@
+
+%.hex: %
+       @$(QUIET_CMD_ECHO) "  OBJCOPY $@"
+       $(Q) $(OBJCOPY)  --output-target=ihex -S $< $@
+
+%.srec: %
+       @$(QUIET_CMD_ECHO) "  OBJCOPY $@"
+       $(Q) $(OBJCOPY)  --output-target=srec -S $< $@
+
+# Syntax: $(call LIBRARY_template,<library-name>)
+define LIBRARY_template
+$(1)_OBJS += $$(filter %.o,$$($(1)_SOURCES:%.c=%.o))
+$(1)_OBJS += $$(filter %.o,$$($(1)_SOURCES:%.cc=%.o))
+$(1)_OBJS += $$(filter %.o,$$($(1)_SOURCES:%.cxx=%.o))
+$(1)_OBJS += $$(filter %.o,$$($(1)_SOURCES:%.S=%.o))
+$(1)_OBJS := $$(sort $$($(1)_OBJS))
+
+SOURCES += $$($(1)_SOURCES)
+
+$(LIB_DIR)/lib$(1).a: $$($(1)_OBJS)
+       @$(QUIET_CMD_ECHO) "  AR      $$@"
+       $(Q) $(AR) rcs $$@ $$^
+endef
+
+
+# Syntax: $(call SOLIB_template,<library-name>)
+define SOLIB_template
+$(1)_OBJSLO += $$(filter %.lo,$$($(1)_SOURCES:%.c=%.lo))
+$(1)_OBJSLO += $$(filter %.lo,$$($(1)_SOURCES:%.cc=%.lo))
+$(1)_OBJSLO += $$(filter %.lo,$$($(1)_SOURCES:%.cxx=%.lo))
+$(1)_OBJSLO += $$(filter %.lo,$$($(1)_SOURCES:%.S=%.lo))
+$(1)_OBJSLO := $$(sort $$($(1)_OBJSLO))
+
+SOLIB_OBJS  += $$($(1)_OBJSLO)
+SOLIB_SOURCES += $$($(1)_SOURCES)
+
+$(LIB_DIR)/lib$(1).so: $$($(1)_OBJSLO)
+       @$(QUIET_CMD_ECHO) "  LINK    $$@"
+       $(Q) $(LD) --shared --soname=lib$(1).so -o $$@ $$^
+endef
+
+# Local Variables:
+# mode:makefile
+# End:
+ifeq ($(OMK_VERBOSE),1)                                      #OMK@include
+CPHEADER_FLAGS += -v
+LNHEADER_FLAGS += -v
+endif
+
+ifneq ($(LN_HEADERS),y)
+define cp_cmd
+( echo "  CP      $(1:$(OUTPUT_DIR)/%=%) -> $(2:$(OUTPUT_DIR)/%=%)"; cp $(CPHEADER_FLAGS) $(1) $(2) )
+endef
+else
+define cp_cmd
+( echo "  LN      $(1:$(OUTPUT_DIR)/%=%) -> $(2:$(OUTPUT_DIR)/%=%)"; [ -f $(1) ] && ln -sf $(LNHEADER_FLAGS) $(1) $(2) )
+endef
+endif
+
+# TODO: Check modification date of changed header files. If it is
+# newer that in source dir, show a warning.
+
+# Syntax: $(call include-pass-template,<include dir>,<keyword>)
+define include-pass-template
+include-pass-local: include-pass-local-$(2)
+include-pass-local-$(2): $$($(2)_GEN_HEADERS) $$(foreach f,$$(renamed_$(2)_GEN_HEADERS),$$(shell echo '$$(f)' | sed -e 's/^\(.*\)->.*$$$$/\1/'))
+       @$$(foreach f, $$($(2)_HEADERS), cmp --quiet $$(SOURCES_DIR)/$$(f) $(1)/$$(notdir $$(f)) \
+          || $$(call cp_cmd,$$(SOURCES_DIR)/$$(f),$(1)/$$(notdir $$(f))) || exit 1 ; )
+       @$$(foreach f, $$($(2)_GEN_HEADERS), cmp --quiet $$(f) $(1)/$$(notdir $$(f)) \
+          || $$(call cp_cmd,$$(LOCAL_BUILD_DIR)/$$(f),$(1)/$$(notdir $$(f))) || exit 1 ; ) # FIXME: Use correct build dir, then document it
+       @$$(foreach f, $$(nobase_$(2)_HEADERS), cmp --quiet $$(SOURCES_DIR)/$$(f) $(1)/$$(f) \
+          || ( mkdir -p $(1)/$$(dir $$(f)) && $$(call cp_cmd,$$(SOURCES_DIR)/$$(f),$(1)/$$(f)) ) || exit 1 ; )
+       @$$(foreach f, $$(renamed_$(2)_HEADERS), \
+          srcfname=`echo '$$(f)' | sed -e 's/^\(.*\)->.*$$$$/\1/'` ; destfname=`echo '$$(f)' | sed -e 's/^.*->\(.*\)$$$$/\1/'` ; \
+          cmp --quiet $$(SOURCES_DIR)/$$$${srcfname} $(1)/$$$${destfname} \
+          || ( mkdir -p `dirname $(1)/$$$${destfname}` && $$(call cp_cmd,$$(SOURCES_DIR)/$$$${srcfname},$(1)/$$$${destfname}) ) || exit 1 ; )
+       @$$(foreach f, $$(renamed_$(2)_GEN_HEADERS), \
+          srcfname=`echo '$$(f)' | sed -e 's/^\(.*\)->.*$$$$/\1/'` ; destfname=`echo '$$(f)' | sed -e 's/^.*->\(.*\)$$$$/\1/'` ; \
+          cmp --quiet $$$${srcfname} $(1)/$$$${destfname} \
+          || ( mkdir -p `dirname $(1)/$$$${destfname}` && $$(call cp_cmd,$$(LOCAL_BUILD_DIR)/$$$${srcfname},$(1)/$$$${destfname}) ) || exit 1 ; )
+endef
+
+# Local Variables:
+# mode:makefile
+# End:
+                                                             #OMK@sysless
+BUILD_DIR_NAME = _build$(addprefix /,$(PREFIX_DIR))
+COMPILED_DIR_NAME = _compiled$(addprefix /,$(PREFIX_DIR))
+
+LOCAL_BUILD_DIR=$(MAKERULES_DIR)/$(BUILD_DIR_NAME)/$(RELATIVE_DIR)
+#$(warning LOCAL_BUILD_DIR = $(LOCAL_BUILD_DIR))
+
+#=====================================================================
+# Common utility rules
+
+link_VARIANTS ?= $(DEFAULT_LD_SCRIPT_VARIANT)
+
+
+#=====================================================================
+# Include correct rules for just running pass
+
+USER_COMPILED_DIR_NAME=$(MAKERULES_DIR)/$(COMPILED_DIR_NAME)
+
+USER_INCLUDE_DIR = $(USER_COMPILED_DIR_NAME)/include
+USER_LIB_DIR     = $(USER_COMPILED_DIR_NAME)/lib
+USER_UTILS_DIR   = $(USER_COMPILED_DIR_NAME)/bin-utils
+USER_TESTS_DIR   = $(USER_COMPILED_DIR_NAME)/bin-tests
+USER_BIN_DIR     = $(USER_COMPILED_DIR_NAME)/bin
+USER_OBJS_DIR    = $(LOCAL_BUILD_DIR)
+
+.PHONY: check-dir
+
+# Some support to serialize some targets for parallel make
+ifneq ($(OMK_SERIALIZE_INCLUDED),y)
+include-pass: check-dir
+library-pass: include-pass
+binary-pass utils-pass: library-pass
+
+override OMK_SERIALIZE_INCLUDED = y
+MAKEOVERRIDES := $(filter-out OMK_SERIALIZE_INCLUDED=n,$(MAKEOVERRIDES))
+endif
+
+# -------------------------------------
+# Rules for compilation for target
+ifdef TARGET_RULE_TEMPLATES
+
+LDFLAGS += -nostartfiles
+
+ # FIXME: These are not used. What they are good for?
+LIB_CPPFLAGS += $(CPPFLAGS)
+LIB_CFLAGS   += $(CFLAGS)
+
+SOLIB_PICFLAGS += -shared -fpic
+
+CFLAGS += -DOMK_FOR_TARGET
+
+INCLUDE_DIR := $(USER_INCLUDE_DIR)
+LIB_DIR     := $(USER_LIB_DIR)
+OBJS_DIR    := $(USER_OBJS_DIR)
+
+$(eval $(COMPILER_DEFS_template))
+
+# Special rules for CMETRIC generated headers
+
+$(foreach cmetrh,$(cmetric_include_HEADERS),$(eval $(call COMPILE_c_o_template,\
+               $(SOURCES_DIR)/$($(basename $(notdir $(cmetrh)))_CMETRIC_SOURCES),\
+               $($(basename $(notdir $(cmetrh)))_CMETRIC_SOURCES:%.c=%.o),)))
+$(foreach cmetrh,$(cmetric_include_HEADERS),$(eval $(call CMETRIC_o_h_template,\
+               $($(basename $(notdir $(cmetrh)))_CMETRIC_SOURCES:%.c=%.o),\
+               $(addprefix $(USER_INCLUDE_DIR)/,$(cmetrh)))))
+
+GEN_HEADERS+=$(cmetric_include_HEADERS:%=$(USER_INCLUDE_DIR)/%)
+
+# Generate rules for compilation of programs and libraries
+ifneq ($(link_VARIANTS),)
+$(foreach prog,$(bin_PROGRAMS),$(foreach link,$(link_VARIANTS),$(eval $(call PROGRAM_template,$(prog),$(USER_BIN_DIR),$(link)))))
+$(foreach prog,$(test_PROGRAMS),$(foreach link,$(link_VARIANTS),$(eval $(call PROGRAM_template,$(prog),$(USER_TESTS_DIR),$(link)))))
+else
+$(foreach prog,$(bin_PROGRAMS),$(eval $(call PROGRAM_template,$(prog),$(USER_BIN_DIR))))
+$(foreach prog,$(test_PROGRAMS),$(eval $(call PROGRAM_template,$(prog),$(USER_TESTS_DIR))))
+endif
+
+$(foreach lib,$(lib_LIBRARIES),$(eval $(call LIBRARY_template,$(lib))))
+$(foreach src,$(lib_obj_SOURCES),$(eval $(call LIBOBJ_template,$(addsuffix $(OBJ_EXT),$(basename $(src))))))
+$(foreach lib,$(shared_LIBRARIES),$(eval $(call SOLIB_template,$(lib))))
+
+
+# lib_obj_SOURCES handling
+lib_OBJS = $(addsuffix $(OBJ_EXT),$(basename $(lib_obj_SOURCES)))
+#$(warning lib_OBJS = $(lib_OBJS))
+SOURCES += $(filter-out %$(OBJ_EXT),$(lib_obj_SOURCES))
+
+$(LIB_DIR)/%$(OBJ_EXT): %$(OBJ_EXT)
+       @echo "  CP      $(^:$(MAKERULES_DIR)/%=%) -> $(@:$(MAKERULES_DIR)/%=%)"
+       $(Q)cp $(CP_FLAGS) $< $@
+
+
+# User-space static libraries and applications object files
+SOURCES := $(sort $(SOURCES))
+#$(warning SOURCES = $(SOURCES))
+
+# User-space shared libraries object files
+SOLIB_SOURCES := $(sort $(SOLIB_SOURCES))
+#$(warning SOLIB_SOURCES = $(SOLIB_SOURCES))
+
+
+# The above generated rules produced $(SOURCES) and $(SOLIB_SOURCES)
+# variables. Now generate rules for compilation of theese sources
+$(foreach src,$(filter %.c,$(SOURCES)),$(eval $(call COMPILE_c_o_template,$(SOURCES_DIR)/$(src),$(src:%.c=%$(OBJ_EXT)),)))
+$(foreach src,$(filter %.cc,$(SOURCES)),$(eval $(call COMPILE_cc_o_template,$(SOURCES_DIR)/$(src),$(src:%.cc=%$(OBJ_EXT)),)))
+$(foreach src,$(filter %.cxx,$(SOURCES)),$(eval $(call COMPILE_cc_o_template,$(SOURCES_DIR)/$(src),$(src:%.cxx=%$(OBJ_EXT)),)))
+$(foreach src,$(filter %$(ASM_EXT),$(SOURCES)),$(eval $(call COMPILE_S_o_template,$(SOURCES_DIR)/$(src),$(src:%$(ASM_EXT)=%$(OBJ_EXT)),)))
+
+$(foreach src,$(filter %.c,$(SOLIB_SOURCES)),$(eval $(call COMPILE_c_o_template,$(SOURCES_DIR)/$(src),$(src:%.c=%.lo),$(SOLIB_PICFLAGS))))
+$(foreach src,$(filter %.cc,$(SOLIB_SOURCES)),$(eval $(call COMPILE_cc_o_template,$(SOURCES_DIR)/$(src),$(src:%.cc=%.lo),$(SOLIB_PICFLAGS))))
+$(foreach src,$(filter %.cxx,$(SOLIB_SOURCES)),$(eval $(call COMPILE_cc_o_template,$(SOURCES_DIR)/$(src),$(src:%.cxx=%.lo),$(SOLIB_PICFLAGS))))
+$(foreach src,$(filter %$(ASM_EXT),$(SOLIB_SOURCES)),$(eval $(call COMPILE_S_o_template,$(SOURCES_DIR)/$(src),$(src:%$(ASM_EXT)=%.lo),$(SOLIB_PICFLAGS))))
+
+library-pass-local: $(addprefix $(USER_INCLUDE_DIR)/,$(cmetric_include_HEADERS)) \
+                   $(lib_LIBRARIES:%=$(LIB_DIR)/$(LIB_PREF)%$(LIB_EXT)) $(shared_LIBRARIES:%=$(LIB_DIR)/$(LIB_PREF)%.so) \
+                   $(addprefix $(LIB_DIR)/,$(lib_OBJS))
+
+ifneq ($(link_VARIANTS),)
+binary-pass-local:  $(foreach link,$(link_VARIANTS),$(bin_PROGRAMS:%=$(USER_BIN_DIR)/%-$(link)) $(test_PROGRAMS:%=$(USER_TESTS_DIR)/%-$(link)) \
+                   $(foreach of,$(OUTPUT_FORMATS),$(bin_PROGRAMS:%=$(USER_BIN_DIR)/%-$(link).$(of)) $(test_PROGRAMS:%=$(USER_TESTS_DIR)/%-$(link).$(of))))
+else
+binary-pass-local:  $(bin_PROGRAMS:%=$(USER_BIN_DIR)/%) $(test_PROGRAMS:%=$(USER_TESTS_DIR)/%) \
+                   $(foreach of,$(OUTPUT_FORMATS),$(bin_PROGRAMS:%=$(USER_BIN_DIR)/%.$(of)) $(test_PROGRAMS:%=$(USER_TESTS_DIR)/%.$(of)))
+endif
+
+endif # TARGET_RULE_TEMPLATES
+
+
+# -------------------------------------
+# Rules for compilation utilities for host (user space)
+ifdef HOST_RULE_TEMPLATES
+
+CROSS_COMPILE =
+TARGET_ARCH =
+
+SOLIB_PICFLAGS += -shared -fpic
+
+# For host compilation, we don't use a specfic ld script
+LD_SCRIPT =
+
+# TODO: It is probably better to use different directories for host
+# includes, libraries and objects
+INCLUDE_DIR := $(USER_INCLUDE_DIR)
+LIB_DIR     := $(USER_LIB_DIR)
+OBJS_DIR    := $(USER_OBJS_DIR)
+
+$(eval $(COMPILER_DEFS_template))
+
+ #User-space static libraries and applications object files
+#SOURCES := $(sort $(SOURCES))
+#$(warning SOURCES = $(SOURCES))
+
+# Generate rules for compilation of utility programs
+$(foreach prog,$(utils_PROGRAMS),$(eval $(call PROGRAM_template,$(prog),$(USER_UTILS_DIR),)))
+
+# The above generated rule produced $(SOURCES) variable. Now generate
+# rules for compilation of theese sources
+$(foreach src,$(filter %.c,$(SOURCES)),$(eval $(call COMPILE_c_o_template,$(SOURCES_DIR)/$(src),$(src:%.c=%$(OBJ_EXT)),)))
+$(foreach src,$(filter %.cc,$(SOURCES)),$(eval $(call COMPILE_cc_o_template,$(SOURCES_DIR)/$(src),$(src:%.cc=%$(OBJ_EXT)),)))
+$(foreach src,$(filter %.cxx,$(SOURCES)),$(eval $(call COMPILE_cc_o_template,$(SOURCES_DIR)/$(src),$(src:%.cxx=%$(OBJ_EXT)),)))
+$(foreach src,$(filter %$(ASM_EXT),$(SOURCES)),$(eval $(call COMPILE_S_o_template,$(SOURCES_DIR)/$(src),$(src:%$(ASM_EXT)=%$(OBJ_EXT)),)))
+
+utils-pass-local: $(utils_PROGRAMS:%=$(USER_UTILS_DIR)/%)
+
+endif # HOST_RULE_TEMPLATES
+
+# Checks for OMK tester
+ifdef OMK_TESTSROOT
+default-config-pass-check include-pass-check:
+library-pass-check binary-pass-check:
+       @[ -x "$(shell which $(CC))" ] || $(call canttest,Cannot find compiler: $(CC))
+endif
+
+#=====================================================================
+# Automatic loading of compiled program by issuing "make load"
+
+ifneq ($(OUTPUT_FORMATS),)
+# Select a file extension (e.g. .bin) for "make load" command to load.
+LOAD_EXTENSION = .$(firstword $(OUTPUT_FORMATS))
+endif
+
+# Syntax: $(call LOAD_PROGRAM_template,<executable-name>,<dir>,<link-variant>)
+# Used to load program to the target hardware
+define LOAD_PROGRAM_template
+.PHONY: load-$(1)$(3:%=-%)
+load-$(1)$(3:%=-%): $(2)/$(1)$(3:%=-%)$(LOAD_EXTENSION)
+       @$(QUIET_CMD_ECHO) "  LOAD    $$<"
+       @if [ -z '$$(LOAD_CMD$(3:%=-%))' ]; then echo "No command for loading applications to '$(3)' is specified."; exit 1; fi
+       $(Q) $$(LOAD_CMD$(3:%=-%)) $$<
+endef
+
+# Syntax: $(call LOAD__RUN_VARIANT_template,<link-variant>)
+# Used to load and/or run non-default variant of the default program
+define LOAD_RUN_VARIANT_template
+.PHONY: load-$(1) run-$(1)
+
+load-$(1): load-$(firstword $(bin_PROGRAMS) $(test_PROGRAMS))-$(1)
+
+run-$(1):
+       @$(QUIET_CMD_ECHO) "  RUN     $(1)"
+       @if [ -z "$(RUN_CMD-$(1))" ]; then echo "No command for running '$(1)' variant is specified."; exit 1; fi
+       $(Q) $(RUN_CMD-$(1))
+
+endef
+
+$(foreach link,$(link_VARIANTS),$(foreach prog,$(bin_PROGRAMS),$(eval $(call LOAD_PROGRAM_template,$(prog),$(USER_BIN_DIR),$(link)))))
+$(foreach link,$(link_VARIANTS),$(foreach prog,$(test_PROGRAMS),$(eval $(call LOAD_PROGRAM_template,$(prog),$(USER_TESTS_DIR),$(link)))))
+$(foreach link,$(link_VARIANTS),$(eval $(call LOAD_RUN_VARIANT_template,$(link))))
+
+.PHONY: load run
+load: $(addprefix load-,$(firstword $(bin_PROGRAMS) $(test_PROGRAMS))-$(firstword $(link_VARIANTS)))
+
+run: run-$(firstword $(link_VARIANTS))
+
+
+
+#=====================================================================
+# Generate pass rules from generic templates
+
+$(eval $(call omk_pass_template, include-pass, $(LOCAL_BUILD_DIR),,$(include_HEADERS)$(nobase_include_HEADERS)$(renamed_include_HEADERS)$(lib_LDSCRIPTS)$(config_include_HEADERS)$(LOCAL_CONFIG_H)))
+$(eval $(call omk_pass_template, library-pass, $(LOCAL_BUILD_DIR),TARGET_RULE_TEMPLATES=y,$(lib_LIBRARIES)$(shared_LIBRARIES)$(lib_obj_SOURCES)))
+$(eval $(call omk_pass_template, binary-pass,  $(LOCAL_BUILD_DIR),TARGET_RULE_TEMPLATES=y,$(bin_PROGRAMS) $(test_PROGRAMS)))
+$(eval $(call omk_pass_template, utils-pass,   $(LOCAL_BUILD_DIR),HOST_RULE_TEMPLATES=y,$(utils_PROGRAMS)))
+$(eval $(call omk_pass_template, dep,    $(LOCAL_BUILD_DIR),,always))
+$(eval $(call omk_pass_template, clean,  $(LOCAL_BUILD_DIR),,always))
+$(eval $(call omk_pass_template, install,$(LOCAL_BUILD_DIR),,always))
+
+
+dep-local:
+
+install-local:
+
+$(eval $(call include-pass-template,$(USER_INCLUDE_DIR),include))
+
+include-pass-local:
+       @$(foreach f, $(lib_LDSCRIPTS), cmp --quiet $(SOURCES_DIR)/$(f) $(USER_LIB_DIR)/$(notdir $(f)) \
+          || $(call cp_cmd,$(SOURCES_DIR)/$(f),$(USER_LIB_DIR)/$(notdir $(f))) || exit 1 ; )
+
+
+.PHONY: clean-custom
+clean-local: clean-custom
+       $(Q)rm -f $(USER_OBJS_DIR)/*.o $(USER_OBJS_DIR)/*.lo \
+              $(USER_OBJS_DIR)/*.d \
+              $(USER_OBJS_DIR)/*.map \
+              $(LOCAL_CONFIG_H:%=$(USER_OBJS_DIR)/%)
+
+check-dir:
+       @$(call mkdir_def,$(USER_INCLUDE_DIR))
+       @$(call mkdir_def,$(USER_LIB_DIR))
+       @$(call mkdir_def,$(USER_BIN_DIR))
+       @$(call mkdir_def,$(USER_UTILS_DIR))
+       @$(call mkdir_def,$(USER_TESTS_DIR))
+
+include-pass-submakes: extra-rules-subdirs
+# Which passes to pass
+default: include-pass library-pass binary-pass utils-pass
+
+# Local Variables:
+# mode:makefile
+# End:
+                                                             #OMK@config_h
+# Syntax: $(call BUILD_CONFIG_H_template,<stamp_dir>,<header_file_path>,<list_of_options_to_export>,<header_barrier>)
+define BUILD_CONFIG_H_template
+
+$(addprefix $(1)/,$(notdir $(addsuffix .stamp,$(2)))) : $(CONFIG_FILES)
+       @$(QUIET_CMD_ECHO) "  CONFGEN $$(@:%.stamp=%)"
+       @if [ ! -d `dirname $(2).tmp` ] ; then \
+               mkdir -p `dirname $(2).tmp` ; fi
+       @echo "/* Automatically generated from */" > "$(2).tmp"
+       @echo "/* config files: $$(^:$(OUTPUT_DIR)/%=%) */" >> "$(2).tmp"
+       $(if $(DOXYGEN),@echo "/** @file */" >> "$(2).tmp")
+       @echo "#ifndef $(4)" >> "$(2).tmp"
+       @echo "#define $(4)" >> "$(2).tmp"
+       @( $(foreach x, $(shell echo '$($(3))' | tr 'x\t ' 'x\n\n' | sed -e 's/^\([^ =]*\)\(=[^ ]\+\|\)$$/\1/' ), \
+               echo '$(x).$($(x))' ; ) echo ; ) | \
+               sed -e '/^[^.]*\.n$$$$/d' -e '/^[^.]*\.$$$$/d' -e 's/^\([^.]*\)\.[ym]$$$$/\1.1/' | \
+               sed -n -e 's/^\([^.]*\)\.\(.*\)$$$$/#define \1 \2/p' \
+                 >> "$(2).tmp"
+       @echo "#endif /*$(4)*/" >> "$(2).tmp"
+       @touch "$$@"
+       @if cmp --quiet "$(2).tmp" "$(2)" ; then rm "$(2).tmp"; \
+       else mv "$(2).tmp" "$(2)" ; \
+       echo "Updated configuration $(2)" ; fi
+
+endef
+
+ifdef LOCAL_CONFIG_H
+
+# This must be declared after the default cflags are assigned!
+# Override is used to override command line assignemnt.
+override CFLAGS += -I $(USER_OBJS_DIR)
+override kernel_INCLUDES += -I $(KERN_OBJS_DIR)
+$(eval $(call BUILD_CONFIG_H_template,$(USER_OBJS_DIR),$(USER_OBJS_DIR)/$(LOCAL_CONFIG_H),default_CONFIG,_LOCAL_CONFIG_H) )
+
+endif
+
+# Special rules for configuration exported headers
+
+#FIXME: The directory for headers should not be specified here.
+$(foreach confh,$(config_include_HEADERS),$(eval $(call BUILD_CONFIG_H_template,$(USER_OBJS_DIR),$(addprefix $(USER_INCLUDE_DIR)/,$(confh)),$(basename $(notdir $(confh)))_DEFINES,\
+_$(basename $(notdir $(confh)))_H \
+)))
+
+config_h_stamp_files = $(addprefix $(USER_OBJS_DIR)/,$(notdir $(addsuffix .stamp,$(config_include_HEADERS) $(LOCAL_CONFIG_H))))
+
+# Add some hooks to standard passes
+include-pass-local: $(config_h_stamp_files)
+
+ifneq ($(KERN_CONFIG_HEADERS_REQUIRED),)
+
+ifdef LOCAL_CONFIG_H
+$(eval $(call BUILD_CONFIG_H_template,$(KERN_OBJS_DIR),$(KERN_OBJS_DIR)/$(LOCAL_CONFIG_H),default_CONFIG,_LOCAL_CONFIG_H) )
+endif
+
+$(foreach confh,$(config_include_HEADERS),$(eval $(call BUILD_CONFIG_H_template,$(KERN_OBJS_DIR),$(addprefix $(KERN_INCLUDE_DIR)/,$(confh)),$(basename $(notdir $(confh)))_DEFINES,\
+_$(basename $(notdir $(confh)))_H \
+)))
+
+kern_config_h_stamp_files = $(addprefix $(KERN_OBJS_DIR)/,$(notdir $(addsuffix .stamp,$(config_include_HEADERS) $(LOCAL_CONFIG_H))))
+
+# Add some hooks to standard passes
+include-pass-local: $(kern_config_h_stamp_files)
+
+endif
+
+clean-local: clean-local-config-h
+
+clean-local-config-h:
+       @$(foreach confh,$(config_h_stamp_files) $(kern_config_h_stamp_files),\
+           if [ -e $(confh) ] ; then rm $(confh) ; fi ; \
+       )
+
+
+# Local Variables:
+# mode:makefile
+# End:
+                                                             #OMK@sources-list
+# Rules that creates the list of files which are used during
+# compilation. The list reflects conditional compilation depending on
+# config.omk and other variables.
+
+SOURCES_LIST_FN=sources.txt
+ifndef SOURCES_LIST
+SOURCES_LIST_DIR:=$(RELATIVE_DIR)
+SOURCES_LIST:=$(OUTPUT_DIR)/$(SOURCES_LIST_DIR)/$(SOURCES_LIST_FN)
+SOURCES_LIST_D := $(LOCAL_BUILD_DIR)/$(SOURCES_LIST_FN).d
+export SOURCES_LIST SOURCES_LIST_DIR SOURCES_LIST_D
+endif
+
+ifeq ($(MAKECMDGOALS),sources-list)
+NEED_SOURCES_LIST=y
+endif
+ifeq ($(MAKECMDGOALS),TAGS)
+NEED_SOURCES_LIST=y
+endif
+ifeq ($(MAKECMDGOALS),tags)
+NEED_SOURCES_LIST=y
+endif
+
+ifeq ($(NEED_SOURCES_LIST),y) # avoid execution of find command bellow if it is not useful
+.PHONY: sources-list
+sources-list: $(SOURCES_LIST)
+
+$(SOURCES_LIST): $(CONFIG_FILES) $(shell find -name $(MAKEFILE_OMK))
+       @$(call mkdir_def,$(dir $(SOURCES_LIST_D)))
+       @echo -n "" > "$(SOURCES_LIST).tmp"
+       @echo -n "" > "$(SOURCES_LIST_D).tmp"
+       @$(MAKE) --no-print-directory sources-list-pass
+       @echo "# Automatically generated list of files in '$(RELATIVE_DIR)' that are used during OMK compilation" > "$(SOURCES_LIST).tmp2"
+       @cat "$(SOURCES_LIST).tmp"|sort|uniq >> "$(SOURCES_LIST).tmp2"
+       @rm "$(SOURCES_LIST).tmp"
+       @mv "$(SOURCES_LIST).tmp2" "$(SOURCES_LIST)"
+       @echo "$(SOURCES_LIST): \\" > "$(SOURCES_LIST_D).tmp2"
+       @cat "$(SOURCES_LIST_D).tmp"|grep -v "$(SOURCES_LIST_D).tmp"|sort|uniq|\
+               sed -e 's/$$/\\/' >> "$(SOURCES_LIST_D).tmp2"
+       @rm "$(SOURCES_LIST_D).tmp"
+       @mv "$(SOURCES_LIST_D).tmp2" "$(SOURCES_LIST_D)"
+endif
+
+$(eval $(call omk_pass_template,sources-list-pass,$$(LOCAL_BUILD_DIR),,always))
+
+sources-list-pass-local:
+       @$(foreach m,$(MAKEFILE_LIST),echo '  $(m)' >> "$(SOURCES_LIST_D).tmp";)
+       @$(foreach h,$(include_HEADERS) $(nobase_include_HEADERS) $(kernel_HEADERS),\
+         echo "$(addsuffix /,$(RELATIVE_DIR:$(SOURCES_LIST_DIR)/%=%))$(h)" >> "$(SOURCES_LIST).tmp";)
+       @$(foreach ch,$(config_include_HEADERS), \
+         echo "$(USER_INCLUDE_DIR:$(OUTPUT_DIR)/$(addsuffix /,$(SOURCES_LIST_DIR))%=%)/$(ch)" >> "$(SOURCES_LIST).tmp";)
+       @$(foreach h,$(renamed_include_HEADERS),echo '$(h)'|sed -e 's|\(.*\)->.*|$(addsuffix /,$(RELATIVE_DIR:$(SOURCES_LIST_DIR)/%=%))\1|' >> "$(SOURCES_LIST).tmp";)
+       @$(foreach bin,$(lib_LIBRARIES) $(shared_LIBRARIES) $(bin_PROGRAMS) $(test_PROGRAMS) $(utils_PROGRAMS) \
+         $(kernel_LIBRARIES) $(rtlinux_LIBRARIES) $(kernel_MODULES),\
+         $(foreach src,$(filter-out %.o,$($(bin)_SOURCES)),echo "$(addsuffix /,$(RELATIVE_DIR:$(SOURCES_LIST_DIR)/%=%))$(src)" >> "$(SOURCES_LIST).tmp";))
+
+############ TAGS ###########
+
+ifeq ($(MAKECMDGOALS),TAGS)
+ETAGS=etags
+TAGS_CMD = $(ETAGS)
+TAGS: $(SOURCES_LIST)
+       @$(MAKE) --no-print-directory do-tags
+endif
+ifeq ($(MAKECMDGOALS),tags) 
+CTAGS=ctags -N
+TAGS_CMD = $(CTAGS)
+tags: $(SOURCES_LIST)
+       @$(MAKE) --no-print-directory do-tags
+endif
+export TAGS_CMD
+
+ifeq ($(MAKECMDGOALS),do-tags)
+.PHONY: do-tags
+do-tags: $(shell sed -e '/^\#/d' $(SOURCES_LIST))
+       @$(QUIET_CMD_ECHO) "  TAGS    $(SOURCES_LIST_FN)"
+       $(Q)$(TAGS_CMD) $^
+endif
+
+############ CSCOPE ###########
+
+cscope: $(SOURCES_LIST)
+       @$(QUIET_CMD_ECHO) "  CSCOPE  < $(SOURCES_LIST_FN)"
+       $(Q)sed -e '/^#/d' $(SOURCES_LIST)|cscope -b -i-
+#FIXME: see doc to -i in cscope(1)
+
+# Local Variables:
+# mode:makefile
+# End:
+                                                             #OMK@localeval
+ifneq ($(local_EVALUATE),)
+#$(warning $(local_EVALUATE))
+$(eval $(local_EVALUATE))
+endif
+
+# Local Variables:
+# mode:makefile
+# End: