Commit 83ed1ca1 authored by Anders Blomdell's avatar Anders Blomdell
Browse files

Commiting hijack drivers for mc (ABB IRC5 master controller)

parents
/*
User visible interface to hijacknet drivers.
Hijacknet drivers are modifications to parts of ABB/VxWorks drivers,
where much of the tNetTask work is moved to the interrupt routines
in order to keep ethernet response time as low as possible (ususally
in 5-15 us range).
Copyright 2012 Anders Blomdell <anders.blomdell@control.lth.se>
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, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <vxWorks.h>
#include <symLib.h>
#include <sysSymTbl.h>
#include <string.h>
#include <hijacknet_private.h>
#include <stdio.h>
HIJACKNET_DRIVER *hijacknet_open(char *name)
{
HIJACKNET_DRIVER *result = NULL;
char open_name[80];
HIJACKNET_DRIVER *(*open)(int unit) = 0;
SYM_TYPE type;
int i, unit;
for (i = strlen(name) ; '0' <= name[i - 1] && name[i - 1] <= '9' ; i--) {
}
unit = atoi(&name[i]);
strncpy(open_name, name, i);
open_name[i] = 0;
strcat(open_name, "_hijacknet_open");
if (OK == symFindByName(sysSymTbl, open_name, (char**)&open, &type)) {
result = open(unit);
if (result) {
strncpy(result->name, name, 80);
} else {
printf("Failed to open hijacknet '%s'\n", name);
}
} else {
printf("Failed to find '%s' symbol\n", open_name);
}
return result;
}
int hijacknet_close(HIJACKNET_DRIVER *driver)
{
return driver->close(driver);
}
static inline int hijacknet_add_hook(struct hijacknet_hook **root,
int ether_type,
int (*hook)(HIJACKNET_DRIVER *driver,
void *data, int length,
void *context),
void *context)
{
int result = 0;
int intLevel;
struct hijacknet_hook *h;
h = malloc(sizeof(*h));
if (!h) {
result = 1;
goto malloc_failed;
}
h->next = NULL;
h->ether_type = ether_type;
h->hook = hook;
h->context = context;
intLevel = intLock();
/* See if hook already installed */
for ( ; *root ; root = &((*root)->next)) {
if ((*root)->ether_type == ether_type &&
(*root)->hook == hook &&
(*root)->context == context) {
result = 2;
goto out;
}
}
/* Put hook last in list */
*root = h;
/* make sure it won't get freed below */
h = NULL;
out:
intUnlock(intLevel);
if (h) {
free(h);
}
malloc_failed:
switch (result) {
case 0: break;
case 1: printf("Failed to allocate hook struct"); break;
case 2: printf("Hook already installed"); break;
default: break;
}
return result;
}
static inline int hijacknet_del_hook(struct hijacknet_hook **root,
int ether_type,
int (*hook)(HIJACKNET_DRIVER *driver,
void *data, int length,
void *context),
void *context)
{
int result = 1;
int intLevel;
struct hijacknet_hook *h = NULL;
intLevel = intLock();
/* See if hook is installed */
for ( ; *root ; root = &((*root)->next)) {
if ((*root)->ether_type == ether_type &&
(*root)->hook == hook &&
(*root)->context == context) {
result = 0;
h = *root;
*root = h->next;
goto out;
}
}
out:
intUnlock(intLevel);
if (h) {
free(h);
}
switch (result) {
case 0: break;
case 1: printf("Hook not found"); break;
default: break;
}
return result;
}
int hijacknet_add_receive_hook(HIJACKNET_DRIVER *driver,
int ether_type,
int (*hook)(HIJACKNET_DRIVER *driver,
void *data, int length,
void *context),
void *context)
{
int result;
result = hijacknet_add_hook(&driver->receive_hook, ether_type, hook, context);
if (result) {
printf(" on %s", driver->name);
}
return result;
}
int hijacknet_del_receive_hook(HIJACKNET_DRIVER *driver,
int ether_type,
int (*hook)(HIJACKNET_DRIVER *driver,
void *data, int length,
void *context),
void *context)
{
int result;
result = hijacknet_del_hook(&driver->receive_hook, ether_type, hook, context);
if (result) {
printf(" on %s", driver->name);
}
return result;
}
int hijacknet_add_send_hook(HIJACKNET_DRIVER *driver,
int ether_type,
int (*hook)(HIJACKNET_DRIVER *driver,
void *data, int length,
void *context),
void *context)
{
int result;
result = hijacknet_add_hook(&driver->send_hook, ether_type, hook, context);
if (result) {
printf(" on %s", driver->name);
}
return result;
}
int hijacknet_del_send_hook(HIJACKNET_DRIVER *driver,
int ether_type,
int (*hook)(HIJACKNET_DRIVER *driver,
void *data, int length,
void *context),
void *context)
{
int result;
result = hijacknet_del_hook(&driver->send_hook, ether_type, hook, context);
if (result) {
printf(" on %s", driver->name);
}
return result;
}
int hijacknet_add_send_done_hook(HIJACKNET_DRIVER *driver,
int ether_type,
int (*hook)(HIJACKNET_DRIVER *driver,
void *data, int length,
void *context),
void *context)
{
int result;
result = hijacknet_add_hook(&driver->send_done_hook, ether_type, hook, context);
if (result) {
printf(" on %s", driver->name);
}
return result;
}
int hijacknet_del_send_done_hook(HIJACKNET_DRIVER *driver,
int ether_type,
int (*hook)(HIJACKNET_DRIVER *driver,
void *data, int length,
void *context),
void *context)
{
int result;
result = hijacknet_del_hook(&driver->send_done_hook, ether_type, hook, context);
if (result) {
printf(" on %s", driver->name);
}
return result;
}
int hijacknet_get_mac_address(HIJACKNET_DRIVER *driver,
unsigned char *mac)
{
return driver->get_mac_address(driver, mac);
}
int hijacknet_send(HIJACKNET_DRIVER *driver,
void *data,
int length)
{
return driver->send(driver, data, length);
}
#ifndef __HIJACK_H__
#define HIJACK_ANY_ETHER_TYPE -1
typedef struct hijacknet_driver HIJACKNET_DRIVER;
HIJACKNET_DRIVER *hijacknet_open(char *name);
int hijacknet_close(HIJACKNET_DRIVER *driver);
int hijacknet_add_receive_hook(HIJACKNET_DRIVER *driver,
int ether_type,
int (*hook)(HIJACKNET_DRIVER *driver,
void *data, int length,
void *context),
void *context);
int hijacknet_del_receive_hook(HIJACKNET_DRIVER *driver,
int ether_type,
int (*hook)(HIJACKNET_DRIVER *driver,
void *data, int length,
void *context),
void *context);
int hijacknet_add_send_hook(HIJACKNET_DRIVER *driver,
int ether_type,
int (*hook)(HIJACKNET_DRIVER *driver,
void *data, int length,
void *context),
void *context);
int hijacknet_del_send_hook(HIJACKNET_DRIVER *driver,
int ether_type,
int (*hook)(HIJACKNET_DRIVER *driver,
void *data, int length,
void *context),
void *context);
int hijacknet_add_completion_hook(HIJACKNET_DRIVER *driver,
int ether_type,
int (*hook)(HIJACKNET_DRIVER *driver,
void *data, int length,
void *context),
void *context);
int hijacknet_del_completion_hook(HIJACKNET_DRIVER *driver,
int ether_type,
int (*hook)(HIJACKNET_DRIVER *driver,
void *data, int length,
void *context),
void *context);
int hijacknet_get_mac_address(HIJACKNET_DRIVER *driver,
unsigned char *mac);
int hijacknet_send(HIJACKNET_DRIVER *driver,
void *data,
int length);
#endif
extern void hijacknet_hpnet_start();
extern void hijacknet_hpnet_handle(unsigned int unit,
unsigned char *data, int length);
/*
Private interface to hijacknet drivers.
Hijacknet drivers are modifications to parts of ABB/VxWorks drivers,
where much of the tNetTask work is moved to the interrupt routines
in order to keep ethernet response time as low as possible (ususally
in 5-15 us range).
Copyright 2012 Anders Blomdell <anders.blomdell@control.lth.se>
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, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <intLib.h>
#include <stdlib.h>
#include <stdio.h>
#include <hijacknet.h>
struct hijacknet_hook {
struct hijacknet_hook *next;
int ether_type;
void *context;
int (*hook)(HIJACKNET_DRIVER *driver,
void *data, int length,
void *context);
};
struct hijacknet_driver {
char name[80];
int (*close)(HIJACKNET_DRIVER *driver);
int (*send)(HIJACKNET_DRIVER *driver,
void *data,
int length);
int (*get_mac_address)(HIJACKNET_DRIVER *driver,
unsigned char mac[6]);
struct hijacknet_hook *receive_hook;
struct hijacknet_hook *send_hook;
struct hijacknet_hook *send_done_hook;
};
static inline int hijacknet_call_hook(struct hijacknet_hook *first,
HIJACKNET_DRIVER *driver,
int ether_type,
unsigned char *data,
int length)
{
int result;
struct hijacknet_hook *hook;
result = length;
for (hook = first ; result && hook ; hook = hook->next) {
if (hook->ether_type == HIJACK_ANY_ETHER_TYPE ||
hook->ether_type == ether_type) {
result = hook->hook(driver,
data, result,
hook->context);
}
}
return result;
}
TARGETS=lth_fixes.mc \
hijacknet.mc \
hijacknet_fei.mc \
hijacknet_hpnet.mc \
hijacknet_lth_net.mc \
fei82557End.mc \
hijacknet_test.mc \
extctrl2014_lc.mc
AUTO_GEN=extctrl2014_lc.c \
extctrl2014_lc.h
GLOBALIZE=netFuncs \
fei82557Int \
fei82557Send \
hpnet_traffic_activated \
hpnetObjects
EXTRA_CFLAGS_hijacknet_lth_net=-I/opt/robot/include
EXTRA_CFLAGS_fei82557End=-Wno-error -Wno-all -Wno-endif-labels
EXTRA_CFLAGS_extctrl2014_lc=-I/usr/include/labcomm \
-DLABCOMM_COMPAT="<labcomm_compat.h>"
ROBOT=
ROBOTWARE=$(shell [ -n "$(ROBOT)" ] && \
../tools/abb_extctrl_setup.py --robot "$(ROBOT)" --robotware)
DESTDIR=$(USER)
VPATH = /opt/robot ../common
.PRECIOUS: %.c %.h
all: $(TARGETS)
mc_test_load: hijack_fei.mc.load spray_test.mc.load
%.mc: %.mc.c
WIND_BASE=/opt/robot/include/vxworks/5.5.1/ \
i586-wrs-vxworks-gcc \
-O3 -Wall -Wno-unused-but-set-variable -Werror \
$(EXTRA_CFLAGS_$*) \
-DPRJ_BUILD -D__PROTOTYPE_5_0 \
-I/opt/robot/include/vxworks/5.5.1/mc/bsp/h \
-I/opt/robot/include/vxworks/5.5.1/mc/bsp/config/abb_extras \
-I/opt/robot/include/vxworks/5.5.1/target/h/wrn/coreip \
-I. \
-I../common \
-o $@ \
-c $<
%.mc: %.c
WIND_BASE=/opt/robot/include/vxworks/5.5.1/ \
i586-wrs-vxworks-gcc \
-O3 -Wall -Wno-unused-but-set-variable -Werror \
$(EXTRA_CFLAGS_$*) \
-DPRJ_BUILD -D__PROTOTYPE_5_0 \
-I/opt/robot/include/vxworks/5.5.1/target/h/wrn/coreip \
-I. \
-I../common \
-o $@ \
-c $<
%_lc.c %_lc.h: %.lc
labcomm2014 --c=$*_lc.c --h=$*_lc.h $<
%.load: %
@ [ -n '$(ROBOT)' ] || ( echo ROBOT not defined ; exit 1)
ncftpput -uu -pp $(ROBOT) /hd0a/$(DESTDIR) $<
.PHONY: globalize
globalize: Makefile ../tools/globalize.py
@ [ -n '$(ROBOT)' ] || ( echo ROBOT file not defined ; exit 1)
../tools/abb_extctrl_setup.py --robot $(ROBOT) \
--globalize mc.globalize.c \
--image mc.sym --patterns 'fei82557.*' \
--symbols $(GLOBALIZE)
$(MAKE) mc.globalize.mc
mv mc.globalize.mc mc.globalize
.PHONY: commands
commands:
@echo "### On host ($(ROBOT) $(ROBOTWARE))"
@$(MAKE) --quiet host_commands
@echo "### On robot:"
@$(MAKE) --quiet robot_commands
.PHONY: host_commands
host_commands:
@ [ -n '$(ROBOT)' ] || ( echo ROBOT not defined >&2 ; exit 1)
@ [ -n '$(ROBOTWARE)' ] || ( echo ROBOTWARE not defined >&2 ; exit 1)
@echo "ncftpput -uu -pp $(ROBOT) /hd0a/$(ROBOTWARE)/bin mc.globalize"
@echo "ncftpput -uu -pp $(ROBOT) /hd0a/$(DESTDIR) lth_fixes.mc"
@echo "ncftpput -uu -pp $(ROBOT) /hd0a/$(DESTDIR) hijacknet_hpnet.mc"
@echo "ncftpput -uu -pp $(ROBOT) /hd0a/$(DESTDIR) hijacknet_fei.mc"
@echo "ncftpput -uu -pp $(ROBOT) /hd0a/$(DESTDIR) hijacknet.mc"
@echo "ncftpput -uu -pp $(ROBOT) /hd0a/$(DESTDIR) hijacknet_test.mc"
.PHONY: robot_commands
robot_commands:
@echo "ld < /hd0a/$(DESTDIR)/lth_fixes.mc"
@echo "lth_fixes"
@echo "ld < /hd0a/$(DESTDIR)/hijacknet_hpnet.mc"
@echo "ld < /hd0a/$(DESTDIR)/hijacknet_fei.mc"
@echo "ld < /hd0a/$(DESTDIR)/hijacknet.mc"
@echo "ld < /hd0a/$(DESTDIR)/hijacknet_test.mc"
.PHONY: clean
clean:
rm -f *~
.PHONY: distclean
distclean: clean
rm -f *.mc mc.globalize $(AUTO_GEN)
hijacknet_fei.mc: fei82557.mc.h hijacknet_private.h
hijacknet.mc: hijacknet.h
#include <vxWorks.h>
#include <stdio.h>
#include <string.h>
/*
nm /tmp/andersb/mc | grep mc_linktimestamp
objdump -s --start-address=0x01688410 --stop-address=0x01688418 mc
objdump -s --start-address=0x016883f0 --stop-address=0x01688406 mc
*/
static char *(*unlinked)() = (char *(*)())0x0;
extern char *mc_linktimestamp();
static char *hijacked_mc_linktimestamp = "#14:34:22/mar 11 2011#";
int hijackOK()
{
if (mc_linktimestamp == unlinked) {
printf("'mc_linktimestamp' symbol not found\n");
return 0;
} else if (strcmp(mc_linktimestamp(), hijacked_mc_linktimestamp)) {
printf("'mc_linktimestamp' strings differ ('%s' != '%s')\n",
mc_linktimestamp(), hijacked_mc_linktimestamp);
return 0;
} else {
return 1;
}
}
#include <netinet/if_ether.h>
#include <drv/end/fei82557End.h>
#include <fei82557EndDefs.h>
/* CSR inline access functions */
//#undef CSR_BYTE_RD
#undef CSR_WORD_RD
//#undef CSR_BYTE_WR
#undef CSR_WORD_WR
#undef CSR_LONG_WR
static inline UINT16 csrGetStatus(DRV_CTRL *drv)
{
return *(UINT16*)((ULONG)drv->pCSR + CSR_STAT_OFFSET);
}
static inline UINT8 csrReadByte(DRV_CTRL *drv, unsigned int offset)
{
return *(UINT8*)((ULONG)drv->pCSR + offset);
}
static inline UINT16 csrReadWord(DRV_CTRL *drv, unsigned int offset)
{
return *(UINT16*)((ULONG)drv->pCSR + offset);
}
static inline void csrWriteByte(DRV_CTRL *drv, unsigned int offset,
UINT8 value)
{
*(UINT8*)((ULONG)drv->pCSR + offset) = value;
CACHE_PIPE_FLUSH();
csrReadByte(drv, CSR_INT_OFFSET);
}
static inline void csrWriteWord(DRV_CTRL *drv, unsigned int offset,
UINT16 value)
{
*(UINT16*)((ULONG)drv->pCSR + offset) = value;
CACHE_PIPE_FLUSH();
csrReadByte(drv, CSR_INT_OFFSET);
}
static inline void csrWriteLong(DRV_CTRL *drv, unsigned int offset,
UINT32 value)
{
*(UINT32*)((ULONG)drv->pCSR + offset) = value;
CACHE_PIPE_FLUSH();
csrReadByte(drv, CSR_INT_OFFSET);
}
static inline void csrWriteVirtToSys(DRV_CTRL *drv, unsigned int offset,
volatile void *value)
{
UINT32 local, bus;
local = (UINT32)CACHE_DRV_VIRT_TO_PHYS(&drv->cacheFuncs, value);
if (drv->board.sysLocalToBus) {
bus = drv->board.sysLocalToBus(drv->unit, local);
} else {
bus = local;
}
csrWriteLong(drv, offset, (ULONG)bus);
}
/* RFD inline access functions */
#undef RFD_BYTE_RD
#undef RFD_WORD_WR