1 /**************************************************************************/
2 /* MTT Library routines to support FESA class */
3 /* Fri 20th October 2006 */
4 /* Julian Lewis AB/CO/HT */
5 /**************************************************************************/
12 #include <sys/ioctl.h>
13 #include <sys/types.h>
15 #include <errno.h> /* Error numbers */
27 /* ================================================================ */
33 static int mtt
= 0; /* File handle on the module */
34 static char objdir
[LN
]; /* Object directory */
35 static MttDrvrInt connected
= 0; /* Connected interrupts */
36 static int noqueueflag
= 0; /* Queueing ON */
37 static int timeout
= 200; /* 2 Seconds */
38 static int first_task
= 1; /* First task number TCB */
39 static int last_task
= MttLibTASKS
; /* Last task number */
40 static int max_size
= MttLibTASK_SIZE
; /* Max task size allowed */
42 static char *errstrings
[MttLibERRORS
] = {
44 /* MttLibErrorNONE, */"No error, all OK",
45 /* MttLibErrorINIT, */"The MTT library has not been initialized",
46 /* MttLibErrorOPEN, */"Unable to open the MTT driver",
47 /* MttLibErrorIO, */"IO error, see errno",
48 /* MttLibErrorSYS, */"Operating system error, see errno",
49 /* MttLibErrorPATH, */"Bad path name syntax",
50 /* MttLibErrorFILE, */"Could not find file, see errno",
51 /* MttLibErrorREAD, */"Can not read file, or file empty",
52 /* MttLibErrorNOMEM, */"Not enough memory",
53 /* MttLibErrorNORELO, */"Task object binary is not relocatable",
54 /* MttLibErrorTOOBIG, */"Task size is too big",
55 /* MttLibErrorEMPTY, */"Object file is empty",
56 /* MttLibErrorFULL, */"No more tasks can be loaded, full up",
57 /* MttLibErrorNOLOAD, */"No such task is loaded",
58 /* MttLibErrorISLOAD, */"Task is already loaded",
59 /* MttLibErrorNAME, */"Illegal task name",
60 /* MttLibErrorLREG, */"No such local register",
61 /* MttLibErrorGREG, */"No such global register"
65 /* =========================== */
66 /* Open MTT driver file handel */
67 static int MttOpen() {
72 for (i
= 1; i
<= SkelDrvrCLIENT_CONTEXTS
; i
++) {
73 sprintf(fnm
, "/dev/%s.%1d", "mtt", i
);
74 if ((fn
= open(fnm
, O_RDWR
, 0)) > 0)
80 /* =========================== */
82 void MttLibUsleep(int dly
) {
83 struct timespec rqtp
, rmtp
; /* 'nanosleep' time structure */
85 rqtp
.tv_nsec
= dly
* 1000;
86 nanosleep(&rqtp
, &rmtp
);
89 /* ============================= */
90 /* Get a file configuration path */
94 static char *defaultconfigpath
= "/dsrc/drivers/mtt/test/mttconfig.linux";
96 static char *defaultconfigpath
= "/dsc/data/mtt/Mtt.conf";
99 static char *configpath
= NULL
;
101 char *MttLibGetFile(char *name
) {
106 static char path
[LN
];
109 gpath
= fopen(configpath
,"r");
115 if (configpath
== NULL
) {
116 configpath
= defaultconfigpath
;
117 gpath
= fopen(configpath
,"r");
120 sprintf(path
,"./%s",name
);
125 bzero((void *) path
,LN
);
128 if (fgets(txt
,LN
,gpath
) == NULL
) break;
129 if (strncmp(name
,txt
,strlen(name
)) == 0) {
130 for (i
=strlen(name
); i
<strlen(txt
); i
++) {
131 if (txt
[i
] != ' ') break;
134 while ((txt
[i
] != ' ') && (txt
[i
] != 0) && (txt
[i
] != '\n')) {
148 /* ================================== */
149 /* Read object code binary from file */
151 MttLibError
MttLibReadObject(FILE *objFile
, ProgramBuf
*code
) {
155 char ln
[LN
], *cp
, *ep
;
157 if (fgets(ln
, LN
, objFile
)) {
159 code
->LoadAddress
= strtoul(cp
, &ep
, 0);
161 code
->InstructionCount
= strtoul(cp
, &ep
, 0);
163 return MttLibErrorREAD
;
165 inst
= (Instruction
*) malloc(sizeof(Instruction
) * code
->InstructionCount
);
167 return MttLibErrorNOMEM
;
169 code
->Program
= inst
;
171 for (i
= 0; i
< code
->InstructionCount
; i
++) {
172 inst
= &(code
->Program
[i
]);
173 bzero((void *) ln
, LN
);
174 if (fgets(ln
, LN
, objFile
)) {
176 inst
->Number
= (unsigned short) strtoul(cp
, &ep
, 0);
178 inst
->Src1
= strtoul(cp
, &ep
, 0);
180 inst
->Src2
= (unsigned short) strtoul(cp
, &ep
, 0);
182 inst
->Dest
= (unsigned short) strtoul(cp
, &ep
, 0);
184 inst
->Crc
= (unsigned short) strtoul(cp
, &ep
, 0);
187 return MttLibErrorNONE
;
190 /* =================================== */
191 /* String to upper case until a space */
193 static void StrToUpper(inp
, out
)
194 char *inp
;char *out
; {
199 for (i
= 0; i
< strlen(inp
); i
++) {
203 if ((*cp
>= 'a') && (*cp
<= 'z'))
210 /* ============================== */
211 /* String to Register */
213 unsigned long MttLibStringToReg(char *name
, MttLibRegType
*lorg
) {
216 unsigned long rn
, en
, st
, of
, lg
, rs
;
217 char upr
[MAX_REGISTER_STRING_LENGTH
+ 1], *cp
, *ep
;
222 if (strlen(upr
) <= MAX_REGISTER_STRING_LENGTH
) {
223 for (i
= 0; i
< REGNAMES
; i
++) {
224 if (strncmp(upr
, Regs
[i
].Name
, strlen(Regs
[i
].Name
)) == 0) {
232 if (strlen(Regs
[i
].Name
) < strlen(name
)) {
233 cp
= name
+ strlen(Regs
[i
].Name
);
234 rn
= strtoul(cp
, &ep
, 0);
236 if ((rn
>= of
) && (rn
<= en
- st
+ of
)) {
254 /* ============================== */
255 /* Register To String */
257 char *MttLibRegToString(int regnum
, MttLibRegType lorg
) {
259 static char name
[MAX_REGISTER_STRING_LENGTH
];
263 if (lorg
== MttLibRegTypeLOCAL
)
266 for (i
= 0; i
< REGNAMES
; i
++) {
268 if ((regnum
>= reg
->Start
) && (regnum
<= reg
->End
)) {
269 rn
= (regnum
- reg
->Start
) + reg
->Offset
;
270 if (reg
->Start
< reg
->End
)
271 sprintf(name
, "%s%1d", reg
->Name
, rn
);
273 sprintf(name
, "%s", reg
->Name
);
280 /* ================================================================ */
281 /* Initialize the MTT library. This routine opens the driver, and */
282 /* initializes the MTT module. The supplied path is where the */
283 /* library will look to find the compiled event table object files. */
284 /* Notice we don't pass event tables through reflective memory. */
285 /* The path name must end with the character '/' and be less than */
286 /* LN (128) characters long. If Path is NULL the default is path is */
287 /* used as defined in libmtt.h DEFAULT_OBJECT_PATH */
291 MttLibError
MttLibInit(char *path
) {
293 uint32_t enb
, stat
, autc
, msk
;
298 strncpy(objdir
, MttLibDEFAULT_OBJECT_PATH
, LN
);
300 if (strlen(path
) >= 1) {
301 strncpy(objdir
, path
, LN
);
302 if ( path
[strlen(objdir
) - 1] != '/')
305 return MttLibErrorPATH
;
314 return MttLibErrorOPEN
;
316 if (ioctl(mtt
, MTT_IOCGSTATUS
, &stat
) < 0) {
318 return MttLibErrorIO
;
321 if ((sysldr
) || ((stat
& MttDrvrStatusENABLED
) == 0)) {
323 if (ioctl(mtt
, MTT_IOCSOUT_ENABLE
, &enb
) < 0) {
326 return MttLibErrorIO
;
330 if ((sysldr
) || ((stat
& MttDrvrStatusUTC_SET
) == 0)) {
331 msk
= MttLibWait(MttDrvrIntPPS
, 0, 200);
332 if (msk
& MttDrvrIntPPS
) {
334 if (time(&tim
) > 0) {
337 if (ioctl(mtt
, MTT_IOCSUTC
, &t
.Second
) < 0) {
340 return MttLibErrorIO
;
345 return MttLibErrorSYS
;
350 return MttLibErrorIO
;
354 if ((sysldr
) || ((stat
& MttDrvrStatusUTC_SENDING_ON
) == 0)) {
356 if (ioctl(mtt
, MTT_IOCSUTC_SENDING
, &autc
) < 0) {
359 return MttLibErrorIO
;
362 return MttLibErrorNONE
;
365 /* ================================================================ */
366 /* Get a string for an MttLibError code */
368 char *MttLibErrorToString(MttLibError err
) {
370 if (err
>= MttLibERRORS
)
371 return "No such error code";
372 return errstrings
[err
];
375 /* ================================================================ */
376 /* Read task program object from MTT program memory */
377 /* The pointers *instructions must be 'free' after the call. */
380 MttLibReadTaskObject(char *name
, ProgramBuf
*pbf
, Instruction
**instructions
)
382 MttDrvrTaskBlock
*tcbp
;
388 return MttLibErrorINIT
;
389 if (name
== NULL
|| !strlen(name
) ||
390 strlen(name
) >= MttLibMAX_NAME_SIZE
||
391 strlen(name
) < MttLibMIN_NAME_SIZE
||
392 !strcmp(name
, "ALL") || !isalpha((int)name
[0])) {
393 return MttLibErrorNAME
;
395 for (i
= 1; i
< strlen(name
); i
++) {
396 if (name
[i
] != '_' && name
[i
] != '.' && !isalnum((int)name
[i
]))
397 return MttLibErrorNAME
;
400 /* fill in task buffer */
401 tcbp
= &tbuf
.ControlBlock
;
402 for (i
= first_task
- 1; i
< last_task
; i
++) {
404 if (ioctl(mtt
, MTT_IOCGTCB
, &tbuf
) < 0)
405 return MttLibErrorIO
;
406 if (strncmp(tbuf
.Name
, name
, MttLibMAX_NAME_SIZE
) == 0)
410 return MttLibErrorNOLOAD
;
412 if (tbuf
.InstructionCount
== 0)
413 return MttLibErrorEMPTY
;
415 /* fetch the program from hardware */
416 pbf
->InstructionCount
= tbuf
.InstructionCount
;
417 pbf
->LoadAddress
= tbuf
.LoadAddress
;
419 *instructions
= malloc(tbuf
.InstructionCount
* sizeof(Instruction
));
420 if (*instructions
== NULL
)
421 return MttLibErrorNOMEM
;
422 pbf
->Program
= *instructions
;
424 if (ioctl(mtt
, MTT_IOCGPROGRAM
, pbf
) < 0) {
426 return MttLibErrorIO
;
428 return MttLibErrorNONE
;
431 /* ================================================================ */
432 /* Load task program object into MTT program memory */
434 MttLibError
MttLibLoadTaskObject(char *name
, ProgramBuf
*pbf
) {
438 MttDrvrTaskBlock
*tcbp
;
439 unsigned long tn
, ftn
, tcnt
, tval
;
443 return MttLibErrorINIT
;
445 if ((name
== NULL
) || (strlen(name
) == 0) || (strlen(name
)
446 >= MttLibMAX_NAME_SIZE
) || (strcmp(name
, "ALL") == 0) || (isalpha(
447 (int) name
[0]) == 0))
448 return MttLibErrorNAME
;
450 for (i
= 1; i
< strlen(name
); i
++) {
451 if ((name
[i
] != '_') && (name
[i
] != '.') && (isalnum((int) name
[i
])
453 return MttLibErrorNAME
;
455 if (strlen(name
) < MttLibMIN_NAME_SIZE
)
456 return MttLibErrorNAME
;
458 if (pbf
->LoadAddress
!= 0)
459 return MttLibErrorNORELO
;
460 if (pbf
->InstructionCount
== 0)
461 return MttLibErrorEMPTY
;
463 tcnt
= (pbf
->InstructionCount
/ (max_size
+ 1)) + 1;
466 tcbp
= &(tbuf
.ControlBlock
);
467 for (i
= first_task
- 1; i
< last_task
; i
++) {
470 if (ioctl(mtt
, MTT_IOCGTCB
, &tbuf
) < 0)
471 return MttLibErrorIO
;
472 if (strncmp(tbuf
.Name
, name
, MttLibMAX_NAME_SIZE
) == 0)
473 return MttLibErrorISLOAD
;
475 for (i
= first_task
- 1; i
< last_task
; i
++) {
478 if (ioctl(mtt
, MTT_IOCGTCB
, &tbuf
) < 0)
479 return MttLibErrorIO
;
480 if (strlen(tbuf
.Name
) == 0) {
482 ioctl(mtt
, MTT_IOCSTASKS_STOP
, &tmsk
);
492 return MttLibErrorNOMEM
;
494 pbf
->LoadAddress
= max_size
* (tn
- 1);
495 if (ioctl(mtt
, MTT_IOCSPROGRAM
, pbf
) < 0)
496 return MttLibErrorIO
;
498 for (i
= ftn
; i
< ftn
+ tval
; i
++) {
500 tbuf
.Fields
= MttDrvrTBFAll
;
501 tbuf
.LoadAddress
= pbf
->LoadAddress
;
502 tbuf
.InstructionCount
= pbf
->InstructionCount
;
504 tcbp
->Pc
= tbuf
.PcStart
;
505 tcbp
->PcOffset
= tbuf
.LoadAddress
;
507 strncpy(tbuf
.Name
, name
, MttLibMAX_NAME_SIZE
);
508 if (ioctl(mtt
, MTT_IOCSTCB
, &tbuf
) < 0)
509 return MttLibErrorIO
;
511 return MttLibErrorNONE
;
514 /* ================================================================ */
515 /* Load/UnLoad a compiled table object from the path specified in */
516 /* the initialization routine into a spare task slot if one exists. */
517 /* Memory handling may result in running tasks being moved around. */
518 /* Task names must be alpha numeric strings with the first char a */
519 /* letter and less than MttLibMAX_NAME_SIZE characters. */
520 /* The special name "ALL" can be used in calls to the UnLoad */
521 /* function to force all tasks and any zombies to be unloaded. */
523 MttLibError
MttLibLoadTask(char *name
) {
532 return MttLibErrorINIT
;
534 if ((name
== NULL
) || (strlen(name
) == 0) || (strlen(name
)
535 >= MttLibMAX_NAME_SIZE
) || (strcmp(name
, "ALL") == 0) || (isalpha(
536 (int) name
[0]) == 0))
537 return MttLibErrorNAME
;
538 for (i
= 1; i
< strlen(name
); i
++) {
539 if ((name
[i
] != '_') && (name
[i
] != '.') && (isalnum((int) name
[i
])
541 return MttLibErrorNAME
;
543 if (strlen(name
) < MttLibMIN_NAME_SIZE
)
544 return MttLibErrorNAME
;
546 sprintf(fname
, "%s%s", objdir
, name
);
547 fhand
= fopen(fname
, "r");
549 return MttLibErrorFILE
;
550 err
= MttLibReadObject(fhand
, &pbf
);
555 err
= MttLibLoadTaskObject(name
, &pbf
);
560 /* ================================================================ */
562 MttLibError
MttLibUnloadTask(char *name
) {
566 MttDrvrTaskBlock
*tcbp
;
571 return MttLibErrorINIT
;
573 if (strcmp(name
, "ALL") == 0)
580 tcbp
= &(tbuf
.ControlBlock
);
581 for (i
= first_task
- 1; i
< last_task
; i
++) {
584 if (ioctl(mtt
, MTT_IOCGTCB
, &tbuf
) < 0)
585 return MttLibErrorIO
;
586 if ((all
) || (strcmp(name
, tbuf
.Name
) == 0)) {
588 err
+= ioctl(mtt
, MTT_IOCSTASKS_STOP
, &tmsk
);
589 bzero((void *) tbuf
.Name
, MttLibMAX_NAME_SIZE
);
590 err
+= ioctl(mtt
, MTT_IOCSTCB
, &tbuf
);
593 if ((err
< 0) && (all
== 0))
594 return MttLibErrorNOLOAD
;
595 return MttLibErrorNONE
;
598 /* ================================================================ */
599 /* Unload all tasks */
601 MttLibError
MttLibUnloadTasks(void)
603 return MttLibUnloadTask("ALL");
606 /* ================================================================ */
607 /* Here the names pointer should be able to store MttLibTABLES char */
608 /* pointers. Loaded tasks reside in MTT memory, and are running if */
609 /* they are not stopped. Do not confuse this state with the run and */
610 /* wait bit masks in the event table task logic. */
612 MttLibError
MttLibGetLoadedTasks(MttLibName
*names
) {
616 MttDrvrTaskBlock
*tcbp
;
620 return MttLibErrorINIT
;
622 tcbp
= &(tbuf
.ControlBlock
);
623 for (i
= first_task
- 1; i
< last_task
; i
++) {
626 if (ioctl(mtt
, MTT_IOCGTCB
, &tbuf
) < 0)
627 return MttLibErrorIO
;
628 if (strlen(tbuf
.Name
))
629 strncpy(names
[i
], tbuf
.Name
, MttLibMAX_NAME_SIZE
);
633 return MttLibErrorNONE
;
636 /* ================================================================ */
638 MttLibError
MttLibGetRunningTasks(MttLibName
*names
) {
642 MttDrvrTaskBlock
*tcbp
;
646 return MttLibErrorINIT
;
648 tcbp
= &(tbuf
.ControlBlock
);
649 for (i
= first_task
- 1; i
< last_task
; i
++) {
652 if (ioctl(mtt
, MTT_IOCGTCB
, &tbuf
) < 0)
653 return MttLibErrorIO
;
654 if (strlen(tbuf
.Name
) && tcbp
->TaskStatus
& MttDrvrTaskStatusRUNNING
)
655 strncpy(names
[i
], tbuf
.Name
, MttLibMAX_NAME_SIZE
);
659 return MttLibErrorNONE
;
662 /* ================================================================ */
663 /* Each task running an event table has MttLibLocakREGISTERS that */
664 /* can be used to contain task parameters such as the run count. */
665 /* The caller must know what these parameters mean for event tasks. */
667 MttLibError
MttLibSetTaskRegister(char *name
, MttLibLocalRegister treg
,
672 MttDrvrTaskBlock
*tcbp
;
674 MttDrvrTaskRegBuf lrb
;
677 return MttLibErrorINIT
;
679 if (treg
>= MttLibLocalREGISTERS
)
680 return MttLibErrorLREG
;
682 tcbp
= &(tbuf
.ControlBlock
);
683 for (i
= first_task
- 1; i
< last_task
; i
++) {
686 if (ioctl(mtt
, MTT_IOCGTCB
, &tbuf
) < 0)
687 return MttLibErrorIO
;
688 if (strcmp(name
, tbuf
.Name
) == 0) {
690 lrb
.RegMask
= 1 << treg
;
691 lrb
.RegVals
[treg
] = val
;
692 if (ioctl(mtt
, MTT_IOCSTRVAL
, &lrb
) < 0)
693 return MttLibErrorIO
;
694 return MttLibErrorNONE
;
697 return MttLibErrorNOLOAD
;
700 /* ================================================================ */
702 MttLibError
MttLibGetTaskRegister(char *name
, MttLibLocalRegister treg
,
703 unsigned long *val
) {
706 MttDrvrTaskBlock
*tcbp
;
708 MttDrvrTaskRegBuf lrb
;
711 return MttLibErrorINIT
;
713 if (treg
>= MttLibLocalREGISTERS
)
714 return MttLibErrorLREG
;
716 tcbp
= &(tbuf
.ControlBlock
);
717 for (i
= first_task
- 1; i
< last_task
; i
++) {
720 if (ioctl(mtt
, MTT_IOCGTCB
, &tbuf
) < 0)
721 return MttLibErrorIO
;
722 if (strcmp(name
, tbuf
.Name
) == 0) {
724 lrb
.RegMask
= 1 << treg
;
725 if (ioctl(mtt
, MTT_IOCGTRVAL
, &lrb
) < 0)
726 return MttLibErrorIO
;
727 *val
= lrb
.RegVals
[treg
];
728 return MttLibErrorNONE
;
731 return MttLibErrorNOLOAD
;
734 /* ================================================================ */
736 MttLibError
MttLibGetTaskRegisters(char *name
, MttLibTaskRegisters
*phLRegs
) {
739 MttDrvrTaskBlock
*tcbp
;
741 MttDrvrTaskRegBuf lreg
;
744 return MttLibErrorINIT
;
746 tcbp
= &(tbuf
.ControlBlock
);
747 for (i
= first_task
- 1; i
< last_task
; i
++) {
750 if (ioctl(mtt
, MTT_IOCGTCB
, &tbuf
) < 0)
751 return MttLibErrorIO
;
752 if (strcmp(name
, tbuf
.Name
) == 0) {
756 if (ioctl(mtt
, MTT_IOCGTRVAL
, &lreg
) < 0)
757 return MttLibErrorIO
;
758 for (j
=0;j
<MttDrvrLRAM_SIZE
;j
++ )
759 phLRegs
->RegVals
[j
]=lreg
.RegVals
[j
];
760 phLRegs
->Task
=lreg
.Task
;
761 phLRegs
->RegMask
=lreg
.RegMask
;
762 return MttLibErrorNONE
;
765 return MttLibErrorNOLOAD
;
768 /* ================================================================ */
769 /* Tasks running event tables can be started, stopped or continued. */
770 /* Starting a task loads its program counter with its start address */
771 /* Stopping a task stops it dead, Continuing a task continues from */
772 /* the last program counter value without reloading it. */
774 MttLibError
MttLibStartTask(char *name
) {
778 MttDrvrTaskBlock
*tcbp
;
783 return MttLibErrorINIT
;
785 tcbp
= &(tbuf
.ControlBlock
);
786 for (i
= first_task
- 1; i
< last_task
; i
++) {
789 if (ioctl(mtt
, MTT_IOCGTCB
, &tbuf
) < 0)
790 return MttLibErrorIO
;
791 if (strcmp(name
, tbuf
.Name
) == 0) {
793 if (ioctl(mtt
, MTT_IOCSTASKS_START
, &tmsk
) < 0)
794 return MttLibErrorIO
;
795 return MttLibErrorNONE
;
798 return MttLibErrorNOLOAD
;
801 /* ================================================================ */
803 MttLibError
MttLibStopTask(char *name
) {
807 MttDrvrTaskBlock
*tcbp
;
812 return MttLibErrorINIT
;
814 tcbp
= &(tbuf
.ControlBlock
);
815 for (i
= first_task
- 1; i
< last_task
; i
++) {
818 if (ioctl(mtt
, MTT_IOCGTCB
, &tbuf
) < 0)
819 return MttLibErrorIO
;
820 if (strcmp(name
, tbuf
.Name
) == 0) {
822 if (ioctl(mtt
, MTT_IOCSTASKS_STOP
, &tmsk
) < 0)
823 return MttLibErrorIO
;
824 return MttLibErrorNONE
;
827 return MttLibErrorNOLOAD
;
830 /* ================================================================ */
832 MttLibError
MttLibContinueTask(char *name
) {
836 MttDrvrTaskBlock
*tcbp
;
841 return MttLibErrorINIT
;
843 tcbp
= &(tbuf
.ControlBlock
);
844 for (i
= first_task
- 1; i
< last_task
; i
++) {
847 if (ioctl(mtt
, MTT_IOCGTCB
, &tbuf
) < 0)
848 return MttLibErrorIO
;
849 if (strcmp(name
, tbuf
.Name
) == 0) {
851 if (ioctl(mtt
, MTT_IOCSTASKS_CONT
, &tmsk
) < 0)
852 return MttLibErrorIO
;
853 return MttLibErrorNONE
;
856 return MttLibErrorNOLOAD
;
859 /* ================================================================ */
860 /* The task status enumeration is defined in the driver includes. */
861 /* By including mttdrvr.h then mtthard.h is also included, and in */
862 /* this hardware description file MtttDrvrTaskStatus is defined. */
863 /* The task status has values like Running, Stopped, Waiting etc */
865 uint32_t MttLibGetTaskStatus(char *name
) {
869 MttDrvrTaskBlock
*tcbp
;
875 tcbp
= &(tbuf
.ControlBlock
);
876 for (i
= first_task
- 1; i
< last_task
; i
++) {
879 if (ioctl(mtt
, MTT_IOCGTCB
, &tbuf
) < 0)
880 return MttLibErrorIO
;
881 if (strcmp(name
, tbuf
.Name
) == 0)
882 return tcbp
->TaskStatus
;
887 static MttLibError
__send_event(int frame
, int priority
)
892 return MttLibErrorINIT
;
895 event
.Priority
= priority
;
896 if (ioctl(mtt
, MTT_IOCSSEND_EVENT
, &event
) < 0)
897 return MttLibErrorIO
;
899 return MttLibErrorNONE
;
902 /* ================================================================ */
903 /* Calling this routine sends out the specified frame immediately. */
904 /* The event will be sent in the high priority queue */
906 MttLibError
MttLibSendEvent(unsigned long frame
) {
908 return __send_event(frame
, 0);
911 MttLibError
MttLibSendEventPrio(unsigned long frame
, int priority
)
913 return __send_event(frame
, priority
);
916 /* ================================================================ */
917 /* This routine allows you to connect to MTT interrupts and wait */
918 /* for them to arrive. You supply a mask defined in mtthard.h that */
919 /* defines which interrupts you want to wait for. The possible */
920 /* interrupts are error conditions, task interrupts, the PPS, SYNC, */
921 /* and software triggered events. The noqueue flag kills the queue */
922 /* if it has a non zero value. Tmo is the timeout in 10ms units. */
923 /* A tmo value of zero means no timeout, hence wait indefinatley. */
925 uint32_t MttLibWait(uint32_t mask
, int noqueue
, int tmo
) {
927 SkelDrvrConnection con
;
934 if ((mask
& connected
) != mask
) {
937 if (ioctl(mtt
, SkelDrvrIoctlCONNECT
, &con
) < 0)
941 if (noqueue
!= noqueueflag
) {
942 if (ioctl(mtt
, SkelDrvrIoctlSET_QUEUE_FLAG
, &noqueue
) < 0)
943 return MttLibErrorIO
;
944 noqueueflag
= noqueue
;
947 if (tmo
!= timeout
) {
948 if (ioctl(mtt
, SkelDrvrIoctlSET_TIMEOUT
, &timeout
) < 0)
949 return MttLibErrorIO
;
954 cc
= read(mtt
, &rbf
, sizeof(SkelDrvrReadBuf
));
958 return rbf
.Connection
.ConMask
;
959 if (mask
& rbf
.Connection
.ConMask
)
960 return rbf
.Connection
.ConMask
;
965 /* ================================================================ */
966 /* The Mtt module status can be read to check its functioning. */
967 /* MttDrvrStatus is defined in mtthard.h. */
969 uint32_t MttLibGetStatus() {
976 if (ioctl(mtt
, MTT_IOCGSTATUS
, &stat
) < 0)
978 return (MttDrvrStatus
) stat
;
981 /* ================================================================ */
982 /* Global Mtt module registers contain stuff like telegrams, UTC */
983 /* and other stuff. The exact meaning of these registers will */
984 /* depend completely on the tasks running in the Mtt module. The */
985 /* caller needs to be aware of the register usage conventions. */
987 MttLibError
MttSetGlobalRegister(MttLibGlobalRegister greg
, unsigned long val
) {
989 MttDrvrGlobalRegBuf grb
;
992 return MttLibErrorINIT
;
994 if (greg
>= MttLibGlobalREGISTERS
)
995 return MttLibErrorGREG
;
999 if (ioctl(mtt
, MTT_IOCSGRVAL
, &grb
) < 0)
1000 return MttLibErrorIO
;
1002 return MttLibErrorNONE
;
1005 /* ================================================================ */
1007 MttLibError
MttGetGlobalRegister(MttLibGlobalRegister greg
, unsigned long *val
) {
1009 MttDrvrGlobalRegBuf grb
;
1012 return MttLibErrorINIT
;
1014 if (greg
>= MttLibGlobalREGISTERS
)
1015 return MttLibErrorGREG
;
1018 if (ioctl(mtt
, MTT_IOCGGRVAL
, &grb
) < 0)
1019 return MttLibErrorIO
;
1022 return MttLibErrorNONE
;
1025 /* ================================================================ */
1026 /* This routine returns the mtt driver file handle so that direct */
1027 /* client ioctl calls can be made. */
1029 int MttLibGetHandle() {
1033 /* ================================================================ */
1034 /* Set task range. */
1035 /* Never call this routine unless the task size is too small. */
1037 MttLibError
MttLibSetTaskRange(unsigned int first
, unsigned int last
,
1038 unsigned int isize
) {
1040 if ((first
< 1) || (first
> MttDrvrTASKS
) || (last
<= first
) || (last
1042 return MttLibErrorNOLOAD
;
1044 first_task
= first
; /* First task number 1..MttDrvrTASKS */
1045 last_task
= last
; /* Last task number 1..MttDrvrTASKS */
1046 max_size
= isize
; /* Number of instructions per task */
1048 return MttLibErrorNONE
;
1050 /* ================================================================ */
1051 /* Get task range. */
1053 void MttLibGetTaskRange(unsigned int *first
, unsigned int *last
,
1054 unsigned int *isize
) {
1056 *first
= first_task
;
1061 /* ================================================================ */
1062 /* Get the TCB number for a given named task, 1..16. If the task is */
1063 /* not found the routine returns zero. */
1065 int MttLibGetTcbNum(char *name
) {
1068 MttDrvrTaskBuf tbuf
;
1069 MttDrvrTaskBlock
*tcbp
;
1075 tcbp
= &(tbuf
.ControlBlock
);
1076 for (i
= first_task
- 1; i
< last_task
; i
++) {
1079 if (ioctl(mtt
, MTT_IOCGTCB
, &tbuf
) < 0)
1080 return MttLibErrorIO
;
1081 if (strcmp(name
, tbuf
.Name
) == 0)
1088 /* ================================================================ */
1089 /* Get host configuration character */
1091 char MttLibGetConfgChar(int n
) {
1093 char *cp
, fname
[LN
], ln
[LN
];
1096 cp
= MttLibGetFile("Mtt.hostconfig");
1099 fp
= fopen(fname
, "r");
1101 cp
= fgets(ln
, LN
, fp
);
1110 /* ================================================================ */
1111 /* Get host configuration ID (M, A or B) */
1113 char MttLibGetHostId() {
1114 return MttLibGetConfgChar(0);
1117 /* ================================================================= */
1118 /* Compile an event table by sending a message to the table compiler */
1119 /* server message queue. The resulting object file is transfered to */
1120 /* the LHC MTGs accross reflective memory. This routine avoids the */
1121 /* need for issuing system calls within complex multithreaded FESA */
1122 /* classes. The table must be loaded as usual and completion must */
1123 /* be checked as usual by looking at the response xmem tables. */
1124 /* If the return code is an IO error this probably means the cmtsrv */
1125 /* task is not running. A SYS error indicates a message queue error. */
1129 /* See libxmem, I had to use xmem to check for update of the object */
1130 /* table. This delays CompileTable until the object is loaded in to */
1131 /* the reflective memory table. */
1132 /* I can't put xmem calls here as others use this library. */
1134 MttLibError
MttLibCompileTable(char *name
) {
1140 q
= mq_open("/tmp/cmtsrv",(O_WRONLY
| O_NONBLOCK
));
1141 if (q
== (mqd_t
) -1) return MttLibErrorIO
;
1143 ql
= mq_send(q
,name
,MttLibMAX_NAME_SIZE
,NULL
);
1146 if (q
== (mqd_t
) -1) {
1147 if (terr
== EAGAIN
) return MttLibErrorIO
;
1148 else return MttLibErrorSYS
;
1150 return MttLibErrorNONE
;