#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+
#include <fs_fpga_int_mem.h>
#include <port.h>
#include <trberror.h>
/* ---------------------------------------------------------------------- */
-static sigset_t blockSet; /* Used for blocking Signals SIGINT and SIGTERM */
+/* Used for blocking Signals SIGINT and SIGTERM */
+static sigset_t blockSet;
static sigset_t blockSetOld;
static int signalsBlocked = 0;
+/* Semaphore handling */
+static int semid = -1;
+static const key_t sem_key = 0x545242;
+
unsigned int trb_debug = 0;
unsigned int trb_lazy = 0;
unsigned int trb_dma = 0;
}
}
+static void fifo_flush(uint8_t channel)
+{
+ uint32_t tmp;
+ uint32_t fifoAddress;
+ unsigned int counter = 0;
+
+ fifoAddress = CHANNEL_N_RECEIVER_DATA | ((channel * 2 + 1) << 4);
+ do {
+ read32_from_FPGA(fifoAddress, &tmp);
+ /* DEBUG INFO */
+ if ((trb_debug > 1) && ((tmp & MASK_FIFO_VALID) != 0)) {
+ fprintf(stderr, "FIFO_%03d: 0x%08x\n", counter, tmp);
+ counter++;
+ }
+ } while ((tmp & MASK_FIFO_VALID) != 0);
+}
+
static int trb_wait_tx_not_busy(uint8_t channel)
{
uint32_t tmp = 0;
}
if (timeout >= MAX_TIME_OUT) {
- trb_fifo_flush(channel);
+ fifo_flush(channel);
trb_errno = TRB_FIFO_TIMEOUT;
return -1;
}
counter = 0;
} else {
/* Error: invalid buffer content, flush FIFO-BUFFER and exit */
- trb_fifo_flush(channel);
+ fifo_flush(channel);
trb_errno = TRB_FIFO_INCOMPLETE_PACKAGE;
return -1;
}
(((*tmp & MASK_FIFO_TYPE) >> SHIFT_FIFO_TYPE) !=
(counter - 1) % 2)) {
/* Error: invalid sequence (not 0, 1, .), flush FIFO-BUFFER and exit */
- trb_fifo_flush(channel);
+ fifo_flush(channel);
trb_errno = TRB_FIFO_SEQUENZ;
return -1;
}
/* First package: headerType must be HDR or TRM */
if (packageCtr == 0) {
if (!((headerType == HEADER_HDR) | (headerType == HEADER_TRM))) {
- trb_fifo_flush(channel);
+ fifo_flush(channel);
trb_errno = TRB_FIFO_INVALID_HEADER;
return -1;
}
!= channel)) {
/* Error Package inconsistencies, flush FIFO-BUFFER and exit */
- trb_fifo_flush(channel);
+ fifo_flush(channel);
trb_errno = TRB_FIFO_HEADERS;
return -1;
}
switch (headerType) {
case HEADER_HDR:
if ((packageCtr - endPointCtr * 2) != 0) {
- trb_fifo_flush(channel);
+ fifo_flush(channel);
trb_errno = TRB_FIFO_INVALID_HEADER;
return -1;
}
if (dataCtr < dsize) {
data[dataCtr++] = (uint32_t)package.F0;
} else {
- trb_fifo_flush(channel);
+ fifo_flush(channel);
trb_errno = TRB_USER_BUFFER_OVF;
return -1;
}
case HEADER_DAT:
if ((packageCtr - endPointCtr * 2) != 1) {
- trb_fifo_flush(channel);
+ fifo_flush(channel);
trb_errno = TRB_FIFO_INVALID_HEADER;
return -1;
}
((uint32_t)package.F2));
endPointCtr++;
} else {
- trb_fifo_flush(channel);
+ fifo_flush(channel);
trb_errno = TRB_USER_BUFFER_OVF;
return -1;
}
break;
default:
- trb_fifo_flush(channel);
+ fifo_flush(channel);
trb_errno = TRB_FIFO_INVALID_HEADER;
return -1;
}
lastHeader = &data[dataCtr];
data[dataCtr++] = (uint32_t)package.F0;
} else {
- trb_fifo_flush(channel);
+ fifo_flush(channel);
trb_errno = TRB_USER_BUFFER_OVF;
return -1;
}
((uint32_t)package.F2));
memLen++;
} else {
- trb_fifo_flush(channel);
+ fifo_flush(channel);
trb_errno = TRB_USER_BUFFER_OVF;
return -1;
}
break;
default:
- trb_fifo_flush(channel);
+ fifo_flush(channel);
trb_errno = TRB_FIFO_INVALID_HEADER;
return -1;
}
if (headerType == HEADER_TRM) break;
if (packageCtr > 1) {
- trb_fifo_flush(channel);
+ fifo_flush(channel);
trb_errno = TRB_INVALID_PKG_NUMBER;
return -1;
}
case HEADER_TRM:
if ((packageCtr > 0) && (dataCtr != len)) {
/* Error invalid length */
- trb_fifo_flush(channel);
+ fifo_flush(channel);
trb_errno = TRB_HDR_DLEN;
return -1;
}
case HEADER_HDR:
if (packageCtr != 0) {
- trb_fifo_flush(channel);
+ fifo_flush(channel);
trb_errno = TRB_FIFO_INVALID_HEADER;
return -1;
}
: (((uint32_t)package.F2 << 16) |
((uint32_t)package.F3));
} else {
- trb_fifo_flush(channel);
+ fifo_flush(channel);
trb_errno = TRB_USER_BUFFER_OVF;
return -1;
}
break;
default:
- trb_fifo_flush(channel);
+ fifo_flush(channel);
trb_errno = TRB_FIFO_INVALID_HEADER;
return -1;
}
switch (headerType) {
case HEADER_HDR:
if ((packageCtr - endPointCtr * 3) != 0) {
- trb_fifo_flush(channel);
+ fifo_flush(channel);
trb_errno = TRB_FIFO_INVALID_HEADER;
return -1;
}
data[dataCtr++] = (uint32_t)sourceAddress;
endPointCtr++;
} else {
- trb_fifo_flush(channel);
+ fifo_flush(channel);
trb_errno = TRB_USER_BUFFER_OVF;
return -1;
}
break;
default:
- trb_fifo_flush(channel);
+ fifo_flush(channel);
trb_errno = TRB_FIFO_INVALID_HEADER;
return -1;
}
if ((packageCtr == 1) && (headerType == HEADER_DAT)) {
if (package.F0 != NET_ACKADDRESS) {
- trb_fifo_flush(channel);
+ fifo_flush(channel);
return -1;
}
}
if (packageCtr > 1) {
- trb_fifo_flush(channel);
+ fifo_flush(channel);
trb_errno = TRB_INVALID_PKG_NUMBER;
return -1;
}
break;
default:
- trb_fifo_flush(channel);
+ fifo_flush(channel);
trb_errno = TRB_FIFO_INVALID_MODE;
return -1;
}
} while (((*tmp & MASK_FIFO_VALID) == 0) && (++timeout < MAX_TIME_OUT));
if (timeout >= MAX_TIME_OUT) {
- trb_fifo_flush(channel);
+ fifo_flush(channel);
trb_errno = TRB_FIFO_INCOMPLETE;
return -1;
}
return -1;
}
- if ((trb_term.status_common & 0x0036) != 0) {
+ if ((trb_term.status_common & 0x003e) != 0) {
trb_errno = TRB_STATUS_ERROR;
return -1;
}
sigprocmask(SIG_SETMASK, &blockSetOld, NULL);
}
+static int lockPorts()
+{
+ struct sembuf sops[2] = {
+ {
+ 0, /* sem_num: We only use one track */
+ 0, /* sem_op: wait for semaphore flag to become zero */
+ SEM_UNDO /* sem_flg: remove sem if process gets killed */
+ },
+ {
+ 0, /* sem_num: We only use one track */
+ 1, /* sem_op: increment semaphore, i.e. lock it */
+ SEM_UNDO | IPC_NOWAIT /* sem_flg: remove sem if process gets killed */
+ }
+ };
+
+ if (semop(semid, sops, 2) == -1) {
+ trb_errno = TRB_SEMAPHORE;
+ return -1;
+ }
+
+ return 0;
+}
+
+static int unlockPorts()
+{
+ struct sembuf sops[1] = {
+ {
+ 0, /* sem_num: We only use one track */
+ -1, /* sem_op: decrement semaphore, i.e. unlock it */
+ IPC_NOWAIT /* */
+ }
+ };
+
+ if (semop(semid, sops, 1) == -1) {
+ trb_errno = TRB_SEMAPHORE;
+ return -1;
+ }
+
+ return 0;
+}
+
/* ----- Global Functions ----------------------------------------------- */
/* Intit FPGA Interface */
return -1;
}
+ /* Get / Create semaphore */
+ if ((semid = semget(sem_key, 1, IPC_CREAT | 0666)) == -1) {
+ trb_errno = TRB_SEMAPHORE;
+ return -1;
+ }
+
return 0;
}
int trb_fifo_flush(uint8_t channel)
{
- uint32_t tmp;
- uint32_t fifoAddress;
- unsigned int counter = 0;
-
trb_errno = TRB_NONE;
if (channel >= 4) {
fprintf(stderr, "Flushing FIFO of channel# %d\n", channel);
}
+ if (lockPorts() == -1) return -1;
+
blockSignals();
- fifoAddress = CHANNEL_N_RECEIVER_DATA | ((channel * 2 + 1) << 4);
- do {
- read32_from_FPGA(fifoAddress, &tmp);
- /* DEBUG INFO */
- if ((trb_debug > 1) && ((tmp & MASK_FIFO_VALID) != 0)) {
- fprintf(stderr, "FIFO_%03d: 0x%08x\n", counter, tmp);
- counter++;
- }
- } while ((tmp & MASK_FIFO_VALID) != 0);
-
+ fifo_flush(channel);
+
unblockSignals();
+
+ if (unlockPorts() == -1) return -1;
return 0;
}
trb_errno = TRB_NONE;
+ if (lockPorts() == -1) return -1;
+
/* Init transfer */
if (trb_init_transfer(3) == -1) {
return -1;
status = trb_fifo_read(3, FIFO_MODE_REG_READ, data, dsize);
unblockSignals();
-
+
+ if (unlockPorts() == -1) return -1;
+
if ((status > 0) && (status % 2 != 0)) {
trb_errno = TRB_INVALID_PKG_NUMBER;
return -1;
}
length = length | (option == 0 ? 0x8000 : 0x0000);
+ if (lockPorts() == -1) return -1;
+
/* Init transfer */
if (trb_init_transfer(3) == -1) {
return -1;
if (trb_debug > 0) {
fprintf(stderr, "Init_Tranfer done.\n");
}
-
+
blockSignals();
/* Build up package and start transfer */
unblockSignals();
+ if (unlockPorts() == -1) return -1;
+
if (status == -1) return status;
/* Check size */
trb_errno = TRB_NONE;
+ if (lockPorts() == -1) return -1;
+
/* Init transfer */
if (trb_init_transfer(3) == -1) {
return -1;
unblockSignals();
+ if (unlockPorts() == -1) return -1;
+
return status;
}
}
config = config | (option == 0 ? 0x8000 : 0x0000);
+ if (lockPorts() == -1) return -1;
+
/* Init transfer */
if (trb_init_transfer(3) == -1) {
return -1;
unblockSignals();
+ if (unlockPorts() == -1) return -1;
+
return status;
}
int trb_read_uid(uint16_t trb_address,
- uint32_t* uidBuffer,
+ uint32_t* data,
unsigned int dsize)
{
int status;
trb_errno = TRB_NONE;
+ if (lockPorts() == -1) return -1;
+
/* Init transfer */
if (trb_init_transfer(3) == -1) {
return -1;
fprintf(stderr, "CMD_READ_UNIQUE_ID started.\n");
}
- status = trb_fifo_read(3, FIFO_MODE_UID, (uint32_t*)uidBuffer, dsize);
+ status = trb_fifo_read(3, FIFO_MODE_UID, (uint32_t*)data, dsize);
unblockSignals();
+ if (unlockPorts() == -1) return -1;
+
if ((status > 0) && (status % 4 != 0)) {
trb_errno = TRB_INVALID_PKG_NUMBER;
return -1;
return -1;
}
+ if (lockPorts() == -1) return -1;
+
/* Init transfer */
if (trb_init_transfer(3) == -1) {
return -1;
unblockSignals();
+ if (unlockPorts() == -1) return -1;
+
if (status == -1) return -1;
if (status != 2) {
trb_errno = TRB_ENDPOINT_NOT_REACHED;
if (data == NULL) return -1;
+ if (lockPorts() == -1) return -1;
+
/* Init transfer IPU Channel */
if (trb_init_transfer(1) == -1) {
return -1;
unblockSignals();
+ if (unlockPorts() == -1) return -1;
+
return status;
}
trb_errno = TRB_NONE;
+ if (lockPorts() == -1) return -1;
+
/* Init transfer trigger */
if (trb_init_transfer(0) == -1) {
return -1;
status = trb_fifo_read(0, FIFO_MODE_NONE, NULL, 0);
unblockSignals();
+
+ if (unlockPorts() == -1) return -1;
if (status == -1) return -1;
trb_errno = TRB_NONE;
+ if (lockPorts() == -1) return -1;
+
/* Init transfer slowcontrol */
if (trb_init_transfer(3) == -1) {
return -1;
/* Check for replay packets (slowcontrol) */
status = trb_fifo_read(3, FIFO_MODE_NONE, NULL, 0);
if (status == -1) {
- trb_fifo_flush(0);
+ fifo_flush(0);
unblockSignals();
+ if (unlockPorts() == -1) return -1;
return -1;
}
unblockSignals();
+ if (unlockPorts() == -1) return -1;
+
if (status == -1) return -1;
return 0;