2 * @file commonGeneration.c
4 * @brief Generates driver files that are common for both, VME and PCI modules.
6 * @author Copyright (C) 2002 CERN. Stuart Baird
7 * @author Copyright (C) 2003 CERN. Alain Gagnaire
8 * @author Copyright (C) 2003 - 2010 CERN. Georgievskiy Yury <ygeorgie@cern.ch>
10 * @date Created on 27/02/2004
12 * @section license_sec License
13 * Released under the GPL
15 #include <sys/types.h>
17 #include "driverGen.h"
18 #include "utilities.h"
20 static void BuildVersionFiles(FILETYPE
);
21 static char *GetGeneralSrcDir();
22 static char *GetLocalDrvrDir();
23 static char *GetLocalFcltyDir();
24 static char *GetLocalInclDir();
25 static char *GetLocalLibDir();
26 static char *GetLocalInstDir();
27 static void BuildTestProgHFile(RegisterDef_t
*, int);
28 static void BuildTestProgConsts(RegisterDef_t
*, int, FILE *);
29 static void BuildTestProgSubMenus(RegisterDef_t
*, BlockDef_t
*, int, FILE *);
30 static void BuildGeneralHeaderFiles();
31 static void BuildGeneralLibraries();
32 static void BuildGeneralInstallProgram();
33 static void BuildGeneralMakefiles();
34 static void BuildGeneralScripts();
35 static int HasExtraneous(RegisterDef_t
*, int);
36 static int HasWriteOnly(RegisterDef_t
*, int);
39 * @brief TODO. REMOVE! (Still used by drmGeneration.c module)
45 void BuildDescsOLD(int numDevs
)
52 devDescFile
= OpenFile(DRIVER_FT
, LOC_MODSRC
, "INST_BI/Dev.desc");
53 simDescFile
= OpenFile(SIM_FT
, LOC_MODSRC
, "INST_BI/Dev.desc");
54 opDescFile
= OpenFile(DRIVER_FT
, LOC_MODSRC
, "INST_BI/.desc");
56 Translate(devDescFile
, "common", "descs/devHead.desc");
57 Translate(simDescFile
, "common", "descs/simHead.desc");
58 Translate(opDescFile
, "common", "descs/opHead.desc");
60 for (i
= 0; i
< numDevs
; i
++) {
61 TranslationSetFancyNum(i
);
62 TranslationSetPlainNum(i
);
63 Translate(devDescFile
, "common", "descs/devDef.desc");
64 Translate(simDescFile
, "common", "descs/devDef.desc");
65 Translate(opDescFile
, "common", "descs/devDef.desc");
74 * @brief Create and open for editing file with the specified name <b>name</b>
76 * @param type -- @b DRIVER_FT, @b SIM_FT, @b COMMON_FT or @b EXACT_FT
77 * @param loc -- file path
78 * @param name -- filename
79 * @param ... -- extra parameters in case if filename @e name contains
80 * conversion specification(s)
82 * - 0x0. Parameter 'name' can consist of conversion
83 * specification (e.g. '%s'), that begins with the character '%'.
84 * In this case one should provide additional parameters for each
86 * - 0x1. This function takes into account currently processed
87 * module type (driver or simulator). If it's a driver, than
88 * suffix 'Drvr' will be added to the generated file name. If it's
89 * simulator, than suffix 'Sim' will be added. It also can be
90 * so-called 'EXACT_FT' type In this case file is created with
91 * exact given name, without adding any specific driver or
92 * simulator prefixes or suffixes. If type is COMMON_FT than
93 * only 'driver name' preffix is added (e.g. SharedCibc), but not
94 * driver or simulator suffixes.
95 * - 0x2. Nested directories, where file should be located are
96 * created also. To denote the fact that nested dir(s) are
97 * needed - one should provide their names in the 'name' parameter
98 * (e.g. 'subdir0/subdir1.../subdirN/filename.c'). Directories
99 * subdir0, subdir1, ... subdirN will be created.
100 * - 0x3. Parameter 'loc' points out initial directory, where
101 * file should be located. See definition of type 'localtion' for
105 * Consider that driver is <b>SHARED_CIBC</b>. This means that
106 * <sys_lower> is "SharedCibc". Also consider that file name that
107 * you want to generate is 'My.c' (@e name parameter):\n
108 * type == DRIVER_FT. <filename> will be 'SharedCibcMyDrvr.c'\n
109 * type == SIM_FT. <filename> will be 'SharedCibcMySim.c'\n
110 * type == COMMON_FT. <filename> will be 'SharedCibcMy.c\n
111 * type == EXACT_FT. <filename> will be 'My.c'\n\n
112 * Depending on 'loc' (location) param, file will be build in
113 * different directories:\n
114 * <I>LOC_MASTER ~/\$(MASTER_DIR)/<filename></I>\n
115 * <I>LOC_GENERAL ~/\$(MASTER_DIR)/\$(GENERAL_DIR)/<filename></I>\n
116 * <I>LOC_MODSRC ~/\$(MASTER_DIR)/\$(DRIVER_DIRECTORY)/<filename></I>\n
117 * <I>LOC_DRVR ~/\$(MASTER_DIR)/\$(DRIVER_DIRECTORY)/driver/<filename></I>\n
118 * <I>LOC_FCLTY ~/\$(MASTER_DIR)/\$(DRIVER_DIRECTORY)/test/<filename></I>\n
119 * <I>LOC_INCL ~/\$(MASTER_DIR)/\$(DRIVER_DIRECTORY)/include/<filename></I>\n
120 * <I>LOC_LIB ~/\$(MASTER_DIR)/\$(DRIVER_DIRECTORY)/lib/<filename></I>\n
121 * <I>LOC_INST ~/\$(MASTER_DIR)/\$(DRIVER_DIRECTORY)/install/<filename></I>\n
122 * <I>LOC_EXPLICIT ~/\$(name) - NOT IMPLEMENTED YET!!! TODO
124 * @note In case of <b>LOC_EXPLICIT</b> you should provide complete directory
125 * path in the <b>name</b> parameter. Afterwards, based on the
126 * <b>type</b> parameter filename will be build.
128 * @return FILE pointer - if succeed.
129 * @return NULL - if error occurs.
131 FILE *OpenFile(FILETYPE type
, location loc
, char *name
, ...)
134 char inputName
[MAXPATHLEN
];
135 char *suffix
= NULL
, *prefix
= NULL
, *ptr
;
139 char *dpPtr
= dirPath
;
143 /* build-up the name first */
145 vsnprintf(inputName
, sizeof(inputName
), name
, ap
);
148 memset(dirPath
, 0, sizeof(dirPath
));
150 if (type
== EXACT_FT
) {
151 prefix
= strdup(inputName
);
153 if (!(suffix
= rindex(inputName
, '.')))
154 return (NULL
); /* wrong name */
156 sz
= strlen(inputName
) - strlen(suffix
);
157 prefix
= (char *)calloc((sz
+ 1), sizeof(char));
158 strncpy(prefix
, inputName
, sz
);
166 ptr
= GetGeneralSrcDir();
172 ptr
= GetLocalDrvrDir();
175 ptr
= GetLocalFcltyDir();
178 ptr
= GetLocalInclDir();
181 ptr
= GetLocalLibDir();
184 ptr
= GetLocalInstDir();
186 case LOC_EXPLICIT
: /* TODO */
189 return NULL
; /* error */
192 strncpy(dirPath
, ptr
, strlen(ptr
));
194 /* Check if nested directories are required */
195 if ((ptr
= strrchr(prefix
, '/'))) {
198 nestDir
= strdup(prefix
); /* copy, to prevent corruption */
201 prefix
= realloc(prefix
, strlen(ptr
) + 1);
202 strcpy(prefix
, tmpBuf
);
204 dpPtr
+= strlen(dirPath
);
208 curDir
= strtok(nestDir
, "/");
209 while (curDir
) { /* create new directories */
210 strcpy(dpPtr
, curDir
);
211 /* TODO. no buffer overflow check! */
212 dpPtr
+= strlen(curDir
);
215 if (MakeSafeDir(dirPath
) == -DRIVER_GEN_BAD
)
217 curDir
= strtok(NULL
, "/");
224 char *final_fn
= GenerateFilename(type
, dirPath
, prefix
,
227 if (!stat(final_fn
, &status
))
228 /* filename is already exist. We should check
229 access permission rights and change them if
230 needed (as we'll need 'w' access right) */
231 chmod(final_fn
, (status
.st_mode
| S_IWUSR
| S_IWGRP
));
233 retFd
= fopen(final_fn
, "w");
241 * @brief Generate driver IOCTL numbers
243 * @param registers -- register description
244 * @param numRegisters -- register amount
245 * @param headerFile -- open header file descriptor
249 void BuildIoctlConsts(RegisterDef_t
* registers
, int numRegisters
,
253 int constCounter
= 0; /* driver ioctl index */
257 /* Set first allowed ioctl number for the driver ioctl numbers
258 Keep the name in accordance with
259 templates/common/header/srvFoot.h! */
260 TranslationSetFancyString("_FIRST__IOCTL_");
262 for (cntr
= 0; cntr
< numRegisters
; cntr
++) {
263 switch (registers
[cntr
].rar
) {
265 TranslationSetPlainNum(constCounter
++);
266 TranslationSetIoctlConst("GET",
267 registers
[cntr
].upperName
);
268 Translate(headerFile
, "common", "header/ioctlConst.h");
271 TranslationSetPlainNum(constCounter
++);
272 TranslationSetIoctlConst("GET_HISTORY",
273 registers
[cntr
].upperName
);
274 Translate(headerFile
, "common", "header/ioctlConst.h");
276 TranslationSetPlainNum(constCounter
++);
277 TranslationSetIoctlConst("SET",
278 registers
[cntr
].upperName
);
279 Translate(headerFile
, "common", "header/ioctlConst.h");
281 case (AMWR
| AMRD
): /* 'rw' */
283 TranslationSetPlainNum(constCounter
++);
284 TranslationSetIoctlConst("GET",
285 registers
[cntr
].upperName
);
286 Translate(headerFile
, "common", "header/ioctlConst.h");
288 TranslationSetPlainNum(constCounter
++);
289 TranslationSetIoctlConst("SET",
290 registers
[cntr
].upperName
);
291 Translate(headerFile
, "common", "header/ioctlConst.h");
299 /* set first allowed user-defined ioctl number */
300 Translate(headerFile
, "common", "dummyTemplates/1NewLine");
301 TranslationSetComment("First allowed number for user-defined ioctl");
302 Translate(headerFile
, "common", "dummyTemplates/comment");
304 TranslationSetPlainNum(constCounter
);
305 TranslationSetIoctlConst("FIRST_USR", "IOCTL");
306 Translate(headerFile
, "common", "header/ioctlConst.h");
310 * @brief Generate module topology.
312 * @param type -- driver (DRIVER_FT) or simulator (SIM_FT)
313 * @param registers -- register description
314 * @param numRegisters -- register amount
315 * @param headerFile -- open header file descriptor
317 * Generate a history structure to store values that were written to writeonly
318 * registers, an extraneous structure for extra driver variables, defined by
319 * the user and a structure for each block that has been defined in the design.
323 void BuildCommonBlocks(int type
, RegisterDef_t
* registers
, int numRegisters
,
327 int theGap
; /* memory gap size betveen the registers */
329 int prevFreeAddr
; /* for memory gap computing */
333 /*--------------------------------------------------------------
334 00. Generate the driver's writeonly structure.
335 --------------------------------------------------------------*/
336 TranslationSetFreeFormat
337 ("keeps last written value of the 'write only' registers");
338 TranslationSetDummyString("");
339 Translate(headerFile
, "common", "header/structHead.h");
340 for (i
= 0; i
< numRegisters
; i
++) {
341 if (registers
[i
].rar
== AMWR
) { /* Is the register writeonly? */
342 TranslationSetRegDepth(registers
[i
].depth
);
343 TranslationSetRegType(registers
[i
].size
);
344 TranslationSetRegName(registers
[i
].name
);
345 if (registers
[i
].depth
<= 1) { /* one register */
346 TranslationSetHexNum(registers
[i
].offset
);
347 TranslationSetFreeFormat("last written value");
348 Translate(headerFile
, "common",
349 "header/recordDefScalar.h");
350 } else { /* massive */
351 TranslationSetFreeFormat("last written values");
352 Translate(headerFile
, "common",
353 "header/recordDefArray.h");
357 Translate(headerFile
, "common", "header/endWriteonly.h");
359 /*-----------------------------------------------------------------
360 01. Generate the driver's extraneous variables structure.
361 -----------------------------------------------------------------*/
362 TranslationSetFreeFormat("user-defined extraneous registers");
363 TranslationSetDummyString("");
364 Translate(headerFile
, "common", "header/structHead.h");
365 for (i
= 0; i
< numRegisters
; i
++) {
366 if (registers
[i
].rar
== AMEX
) { /* is it is extraneous? */
367 TranslationSetRegDepth(registers
[i
].depth
);
368 TranslationSetRegType(registers
[i
].size
);
369 TranslationSetRegName(registers
[i
].name
);
370 if (registers
[i
].depth
<= 1) { /* one register */
371 TranslationSetFreeFormat("user-def reg");
372 Translate(headerFile
, "common",
373 "header/recordDefScalar.h");
374 } else { /* massive */
375 TranslationSetFreeFormat("user-def regs");
376 Translate(headerFile
, "common",
377 "header/recordDefArray.h");
381 Translate(headerFile
, "common", "header/endExtraneous.h");
383 /*------------------------------------------------------
384 02. Generate device memory map topology structures.
385 ------------------------------------------------------*/
387 for (i
= 0; i
< numRegisters
; i
++) {
388 if (registers
[i
].rar
!= AMEX
) {
389 /* exclude extraneous registers */
391 /* If we just ended a block then we must be
392 starting a new one */
393 TranslationSetFreeFormat
394 ("Blk[#%d]@addr[#%d] Offs 0x%x."
395 " Sz %d bytes. %d reg(s). %d gap(s)",
396 registers
[i
].blockP
->blockID
,
397 registers
[i
].blockP
->blkBaseAddr
,
398 registers
[i
].blockP
->offset
,
400 registers
[i
].blockP
->blksz_sim
:
401 registers
[i
].blockP
->blksz_drvr
,
402 registers
[i
].blockP
->reg_am
,
403 calc_block_gap_amount(®isters
[i
]));
404 TranslationSetDummyString("volatile");
405 Translate(headerFile
, "common",
406 "header/structHead.h");
410 If this is the first register in a block, check that
411 it's offset is 0. If not then insert some dummy
412 records into the structure to take up the spare
416 if (type
== DRIVER_FT
) {
417 /* we need to set gaps only for real driver */
419 /* If we just ended a block then we
420 must be starting a new one */
422 theGap
= registers
[i
].offset
;
425 registers
[i
- 1].offset
+
426 ((registers
[i
- 1].depth
) ?
427 registers
[i
- 1].depth
:
428 1) * registers
[i
- 1].regSize
;
430 registers
[i
].offset
- prevFreeAddr
;
434 TranslationSetFancyNum(i
);
435 TranslationSetRegDepth(theGap
);
436 TranslationSetFreeFormat("0x%x - 0x%x",
440 Translate(headerFile
, "common",
441 "header/dummyRecord.h");
445 /* Produce a record in the structure for our register */
446 TranslationSetRegType(registers
[i
].size
);
447 TranslationSetRegName(registers
[i
].name
);
448 TranslationSetRegDepth(registers
[i
].depth
);
449 if (registers
[i
].depth
<= 1) { /* one register */
450 TranslationSetFreeFormat("0x%x",
451 registers
[i
].offset
);
452 Translate(headerFile
, "common",
453 "header/recordDefScalar.h");
454 } else { /* massive */
455 /* register offset (i.e. Base Address) */
456 unsigned int regBA
= registers
[i
].offset
;
458 /* last valid massive address (i.e. address
459 of the last register in massive) */
460 unsigned int regLA
= regBA
+
461 (registers
[i
].depth
- 1) *
462 registers
[i
].regSize
;
463 TranslationSetFreeFormat("0x%x - 0x%x", regBA
,
465 Translate(headerFile
, "common",
466 "header/recordDefArray.h");
469 /* Determine whether we should terminate this
471 if (i
== numRegisters
- 1)
473 else if (registers
[i
].blockP
->blockID
!=
474 registers
[i
+ 1].blockP
->blockID
)
480 TranslationSetFancyNum(registers
[i
].blockP
->
482 if (type
== DRIVER_FT
)
483 Translate(headerFile
, "common",
484 "header/endDrvrBlock.h");
486 Translate(headerFile
, "common",
487 "header/endSimBlock.h");
489 } /* end of 'rar != AMEX' */
494 * @brief Generate @b DEPRECATED @e IoctlAccess library.
496 * @param registers -- register description
497 * @param numRegisters -- register amount
498 * @param blocks -- block description
499 * @param numBlocks -- block amount
501 * This library enables user to use old-style ioctl calls to access the driver.
505 void BuildIoctlLibrary(RegisterDef_t
* registers
, int numRegisters
,
506 BlockDef_t
* blocks
, int numBlocks
)
512 char *bus
= TranslationGetBus(); /* 'VME' or 'DRM' */
515 libraryFile
= OpenFile(COMMON_FT
, LOC_LIB
, "IoctlAccess.c");
516 headerFile
= OpenFile(COMMON_FT
, LOC_INCL
, "IoctlAccess.h");
518 Translate(libraryFile
, bus
, "lib/IoctlAccess/head.c");
519 Translate(libraryFile
, "common", "lib/ioctlAccess/enableAccess.c");
521 TranslationSetFreeFormat("%s", DG_INC_DIR
);
522 Translate(headerFile
, bus
, "lib/IoctlAccess/headerHead.h");
523 Translate(headerFile
, "common", "lib/ioctlAccess/enableAccess.h");
525 /* Generate the get and set functions for each register and write to
526 the library source file, and generate function prototypes for each
527 get and set function and write to the library's header file. */
528 for (cntr
= 0; cntr
< numRegisters
; cntr
++) {
529 TranslationSetRegName(registers
[cntr
].name
);
530 TranslationSetRegType(registers
[cntr
].size
);
531 TranslationSetRegDepth(registers
[cntr
].depth
);
533 if (registers
[cntr
].depth
<= 1)
534 strcpy(accessType
, "Scalar");
536 strcpy(accessType
, "Array");
538 switch (registers
[cntr
].rar
) {
540 TranslationSetIoctlConst("GET",
541 registers
[cntr
].upperName
);
542 Translate(libraryFile
, "common",
543 "lib/ioctlAccess/get%s.c", accessType
);
544 Translate(headerFile
, "common",
545 "lib/ioctlAccess/get%s.h", accessType
);
548 TranslationSetIoctlConst("GET_HISTORY",
549 registers
[cntr
].upperName
);
550 Translate(libraryFile
, "common",
551 "lib/ioctlAccess/getLastHisWo%s.c",
553 Translate(headerFile
, "common",
554 "lib/ioctlAccess/getLastHisWo%s.h",
557 TranslationSetIoctlConst("SET",
558 registers
[cntr
].upperName
);
559 Translate(libraryFile
, "common",
560 "lib/ioctlAccess/set%s.c", accessType
);
561 Translate(headerFile
, "common",
562 "lib/ioctlAccess/set%s.h", accessType
);
564 case (AMWR
| AMRD
): /* 'rw' */
566 TranslationSetIoctlConst("GET",
567 registers
[cntr
].upperName
);
568 Translate(libraryFile
, "common",
569 "lib/ioctlAccess/get%s.c", accessType
);
570 Translate(headerFile
, "common",
571 "lib/ioctlAccess/get%s.h", accessType
);
573 TranslationSetIoctlConst("SET",
574 registers
[cntr
].upperName
);
575 Translate(libraryFile
, "common",
576 "lib/ioctlAccess/set%s.c", accessType
);
577 Translate(headerFile
, "common",
578 "lib/ioctlAccess/set%s.h", accessType
);
585 Translate(headerFile
, "common", "lib/ioctlAccess/headerFoot.h");
592 * @brief Builds test program that user will use to test driver/simulator.
594 * @param registers -- register description
595 * @param numRegisters -- register amount
596 * @param blocks -- block description
597 * @param numBlocks -- block amount
601 void BuildTestProgram(RegisterDef_t
* registers
, int numRegisters
,
602 BlockDef_t
* blocks
, int numBlocks
)
604 FILE *tstFileC
= OpenFile(COMMON_FT
, LOC_FCLTY
, "Test.c");
605 char *bus
= TranslationGetBus(); /* 'VME' or 'DRM' */
606 unsigned int freeEntry
= TST_PROG_FIRST_FREE_ENTRY
; /* */
611 /* Generate the needed block size consts and register
612 description strings */
613 BuildTestProgHFile(registers
, numRegisters
);
614 BuildTestProgConsts(registers
, numRegisters
, tstFileC
);
616 /* Generate the remainder of the head and the start of main */
617 Translate(tstFileC
, "common", "testProg/common/testMainBegin.c");
618 Translate(tstFileC
, "common", "testProg/testMainMenu.c");
620 /* For each block that's been defined, generate an entry in the
621 program's main menu. */
622 for (count
= freeEntry
, i
= 0; i
< numBlocks
; i
++, count
++) {
623 TranslationSetFancyNum(count
);
624 TranslationSetPlainNum(blocks
[i
].blockID
);
625 Translate(tstFileC
, "common",
626 "testProg/common/mainMenuEntry.c");
629 /* Add the PCI config menu item (in case of DRM usage),
630 and the other common options. */
631 Translate(tstFileC
, bus
, "testProg/mainMenuFoot.c");
632 Translate(tstFileC
, "common", "testProg/mainCaseHead.c");
634 /* Generate the case statements for each of the main menu entries. */
635 for (count
= freeEntry
, i
= 0; i
< numBlocks
; i
++, count
++) {
636 TranslationSetFancyNum(blocks
[i
].blockID
);
637 TranslationSetPlainNum(count
);
638 Translate(tstFileC
, "common", "testProg/common/case.c");
641 TranslationSetPlainNum(count
);
642 Translate(tstFileC
, bus
, "testProg/mainCaseFoot.c");
644 BuildTestProgSubMenus(registers
, blocks
, numRegisters
, tstFileC
);
650 * @brief Generates the makefiles that are used to build the generated
657 void BuildMakefiles()
660 char dirPath
[MAXPATHLEN
] = { 0 };
665 mkfd
= OpenFile(EXACT_FT
, LOC_MODSRC
, "Makefile.base");
666 Translate(mkfd
, "common", "makefiles/Makefile.base");
669 /* Specific Makefile */
670 mkfd
= OpenFile(EXACT_FT
, LOC_MODSRC
, "Makefile.specific");
671 Translate(mkfd
, "common", "makefiles/Makefile.specific");
674 /* "Which dirs to compile" Makefile */
675 mkfd
= OpenFile(EXACT_FT
, LOC_MODSRC
, "Makefile");
676 Translate(mkfd
, "common", "makefiles/Makefile");
680 mkfd
= OpenFile(EXACT_FT
, LOC_MODSRC
, "deliver.mk");
681 Translate(mkfd
, "common", "makefiles/deliver.mk");
684 /* Library Makefile */
685 mkfd
= OpenFile(EXACT_FT
, LOC_LIB
, "Makefile");
686 Translate(mkfd
, "common", "makefiles/libModule.mk");
689 /* Driver Makefiles */
690 mkfd
= OpenFile(EXACT_FT
, LOC_DRVR
, "makefiles/drvr-linux.mk");
691 Translate(mkfd
, "common", "makefiles/drvr-linux.mk");
694 mkfd
= OpenFile(EXACT_FT
, LOC_DRVR
, "makefiles/drvr-lynx.mk");
695 Translate(mkfd
, "common", "makefiles/drvr-lynx.mk");
698 mkfd
= OpenFile(EXACT_FT
, LOC_DRVR
, "makefiles/Kbuild");
699 Translate(mkfd
, "common", "makefiles/Kbuild");
702 mkfd
= OpenFile(EXACT_FT
, LOC_DRVR
, "makefiles/drvr-paramount.mk");
703 Translate(mkfd
, "common", "makefiles/drvr-paramount.mk");
706 mkfd
= OpenFile(EXACT_FT
, LOC_DRVR
, "Makefile");
707 Translate(mkfd
, "common", "makefiles/Makefile.drvr");
710 mkfd
= OpenFile(EXACT_FT
, LOC_DRVR
, "compiledrvr");
711 Translate(mkfd
, "common", "makefiles/compiledrvr");
713 S_IRUSR
| S_IWUSR
| S_IXUSR
| S_IRGRP
| S_IXGRP
| S_IROTH
);
716 /* we need this symlink for Kbuild to work */
717 sprintf(dirPath
, "%s%s", GetLocalDrvrDir(), "/Kbuild");
718 symlink("makefiles/Kbuild", dirPath
);
720 /* Facility (test program) Makefile */
721 mkfd
= OpenFile(EXACT_FT
, LOC_FCLTY
, "Makefile");
722 TranslationSetFreeFormat("%s", DAL_DIR
);
723 Translate(mkfd
, "common", "makefiles/test.mk");
726 /* Include Makefile */
727 mkfd
= OpenFile(EXACT_FT
, LOC_INCL
, "Makefile");
728 Translate(mkfd
, "common", "makefiles/include.mk");
731 /* Install program entry point Makefile */
732 mkfd
= OpenFile(EXACT_FT
, LOC_INST
, "Makefile");
733 TranslationSetFreeFormat("%s", DAL_DIR
);
734 Translate(mkfd
, "common", "makefiles/installso.mk");
739 * @brief Create (if it was not done yet) main installation directory, where
740 * newly created drivers are located.
742 * @param mdn -- Module Description
743 * If NULL, current master directory name will be returned.
745 * Will be created only *once*. Creates all general-purpose files that should
746 * present in the master diretory (user-part source copy utility for example).
748 * If directory is created already, than no action perfomed exept of returning
749 * the directory name.
751 * @return Main Installation Directory name
753 char *get_mid(struct mdescr
*md
)
755 static char *mainDir
= NULL
; /* container */
756 char *cwd
= ""; /* current working directory */
759 if (mainDir
) /* master dir was already created */
762 /* master dir is not yet created */
763 mainDir
= (char *)calloc((strlen(cwd
) + strlen(md
->mdn
) + 2), sizeof(char));
764 sprintf(mainDir
, "%s%s", cwd
, md
->mdn
);
766 ret
= MakeSafeDir(mainDir
);
767 if (ret
== -DRIVER_GEN_BAD
)
768 exit(EXIT_FAILURE
); /* 1 */
770 /* make symlinks to the general utilities
771 (script for copy user-part src code) */
774 char loc_link
[128]; /* local utility symlink */
775 char glob_link
[128]; /* global utility symlink */
778 sprintf(loc_link
, "%s/%s", mainDir
, UTIL_CP_USR_PT_LOC
);
779 sprintf(glob_link
, "%s/%s", mainDir
, UTIL_CP_USR_PT_GLOB
);
780 sprintf(gen_dir
, "%s/%s", mainDir
, GENERAL_DIR
);
782 if (lstat(glob_link
, &status
)) /* global symlink doesn't
784 symlink(GenerateFilename(EXACT_FT
, DG_DIR_PATH
,
785 "scripts/" UTIL_CP_USR_PT_GLOB
, NULL
, NULL
),
788 if (!stat(gen_dir
, &status
))
789 /* we have 'general' dir locally, so create local
791 if (lstat(loc_link
, &status
)) /* local symlink doesn't
793 symlink(GenerateFilename
794 (EXACT_FT
, GENERAL_DIR
,
795 UTIL_CP_USR_PT_GLOB
, NULL
, NULL
),
803 * @brief Get Module Source code Directory.
805 * @param md -- module description
807 * Creates directory, where Driver/Simulator source code of a currently
808 * processed module will be located. If directory is already created, than no
809 * action perfomed exept of returning the directory name.
811 * @return directory name for driver src code.
813 char *get_msd(struct mdescr
*md
)
815 static char *sourceDir
= NULL
; /* container */
818 char timeStr
[MAX_STR
];
821 if (sourceDir
) /* driver source dir is already created */
824 /* Driver directory is not created yet */
826 tmPtr
= localtime(&theTime
);
828 /* obfuscate 'gcc' to bypass warnings about format string */
829 tFmt
= "%d%b%G.%Hh%Mm%Ss";
831 strftime(timeStr
, sizeof(timeStr
), tFmt
, tmPtr
);
833 sourceDir
= (char *)calloc(MAXPATHLEN
, sizeof(char));
835 snprintf(sourceDir
, MAXPATHLEN
, "%s/%s",
836 get_mid(NULL
), TranslationGetModName());
838 snprintf(sourceDir
, MAXPATHLEN
, "%s/%s.%s",
839 get_mid(NULL
), TranslationGetModName(), timeStr
);
841 if (MakeSafeDir(sourceDir
) == -DRIVER_GEN_BAD
)
842 exit(EXIT_FAILURE
); /* 1 */
848 * @brief Build the driver's Ioctl routine.
850 * @param registers -- register description
851 * @param numRegisters -- register amount
852 * @param driverFile -- open file descriptor
854 void BuildDrvrSimIoctl(RegisterDef_t
* registers
, int numRegisters
,
860 Translate(driverFile
, "common", "driver/ioctl/head.c");
862 /* first, build 'service' registers ioctl */
863 TranslationSetBaseAddr("");
864 for (cntr
= 0; cntr
< GetSrvRegNum(); cntr
++) {
865 TranslationSetRegName(srv_ioctl
[cntr
].name
);
866 switch (srv_ioctl
[cntr
].rar
) {
868 TranslationSetIoctlConst("GET", srv_ioctl
[cntr
].name
);
869 TranslationSetRegType("get");
870 Translate(driverFile
, "common",
871 "driver/ioctl/getSetReg.c");
874 TranslationSetIoctlConst("SET", srv_ioctl
[cntr
].name
);
875 TranslationSetRegType("set");
876 Translate(driverFile
, "common",
877 "driver/ioctl/getSetReg.c");
879 case (AMWR
| AMRD
): /* 'rw' */
880 TranslationSetIoctlConst("GET", srv_ioctl
[cntr
].name
);
881 TranslationSetRegType("get");
882 Translate(driverFile
, "common",
883 "driver/ioctl/getSetReg.c");
885 TranslationSetIoctlConst("SET", srv_ioctl
[cntr
].name
);
886 TranslationSetRegType("set");
887 Translate(driverFile
, "common",
888 "driver/ioctl/getSetReg.c");
891 TranslationSetIoctlConst("", srv_ioctl
[cntr
].name
);
892 TranslationSetRegType("srv_func");
893 Translate(driverFile
, "common",
894 "driver/ioctl/getSetReg.c");
899 /* now build-up r/w operations for the normal registers */
900 for (cntr
= 0; cntr
< numRegisters
; cntr
++) {
901 TranslationSetRegName(registers
[cntr
].name
);
902 switch (registers
[cntr
].rar
) {
903 case AMRD
: /* 'r' read-only reg */
904 TranslationSetIoctlConst("GET",
905 registers
[cntr
].upperName
);
906 TranslationSetBaseAddr("");
907 TranslationSetRegType("get");
908 Translate(driverFile
, "common",
909 "driver/ioctl/getSetReg.c");
911 case AMWR
: /* 'w' write-only reg */
912 TranslationSetIoctlConst("GET_HISTORY",
913 registers
[cntr
].upperName
);
914 TranslationSetBaseAddr("wo_");
915 TranslationSetRegType("get");
916 Translate(driverFile
, "common",
917 "driver/ioctl/getSetReg.c");
919 TranslationSetIoctlConst("SET",
920 registers
[cntr
].upperName
);
921 TranslationSetBaseAddr("");
922 TranslationSetRegType("set");
923 Translate(driverFile
, "common",
924 "driver/ioctl/getSetReg.c");
926 case (AMWR
| AMRD
): /* 'rw' read/write reg */
927 TranslationSetIoctlConst("GET",
928 registers
[cntr
].upperName
);
929 TranslationSetBaseAddr("");
930 TranslationSetRegType("get");
931 Translate(driverFile
, "common",
932 "driver/ioctl/getSetReg.c");
934 TranslationSetIoctlConst("SET",
935 registers
[cntr
].upperName
);
936 TranslationSetBaseAddr("");
937 TranslationSetRegType("set");
938 Translate(driverFile
, "common",
939 "driver/ioctl/getSetReg.c");
941 case AMEX
: /* 'e' extraneous (i.e. w/r) reg */
942 TranslationSetIoctlConst("GET",
943 registers
[cntr
].upperName
);
944 TranslationSetBaseAddr("ex_");
945 TranslationSetRegType("get");
946 Translate(driverFile
, "common",
947 "driver/ioctl/getSetReg.c");
949 TranslationSetIoctlConst("SET",
950 registers
[cntr
].upperName
);
951 TranslationSetBaseAddr("ex_");
952 TranslationSetRegType("set");
953 Translate(driverFile
, "common",
954 "driver/ioctl/getSetReg.c");
961 Translate(driverFile
, "common", "driver/ioctl/foot.c");
965 * @brief Generate the get and set (or r/w) functions
967 * @param registers -- register description
968 * @param numRegisters -- register amount
969 * @param vmeInfo -- @e vme description
971 * Header file with their declaration is also created. This functions are used
972 * by the driver ioctl routine to access hardware registers. @b CH in the name
973 * stands for @e c source file and @e h header file.
977 void BuildGetSetRegCH(RegisterDef_t
* registers
, int numRegisters
,
980 FILE *c_fd
= OpenFile(COMMON_FT
, LOC_DRVR
, "GetSetReg.inc.c");
981 FILE *h_fd
= OpenFile(COMMON_FT
, LOC_INCL
, "GetSetReg.h");
982 char *bus
= TranslationGetBus(); /* 'VME' or 'DRM' */
983 char accessType
[MIN_STR
], *strDps
, singularity
[16], *rsz
;
985 long dps
; /* address space data port size */
986 char singular_comment_str
[256];
988 " These functions are used to deliver register values directly"
989 " to the user\n space.\n\n"
990 " API is the following:\n"
991 " 1 param -- statics table\n\n"
992 " 2 param -- ioctl argument in predefined format:\n"
993 " Massive of 3 elements, each is 4 bytes long.\n"
994 " [0] - user-space address\n"
995 " [1] - number of elements to r/w\n"
996 " [2] - element index, starting from zero\n\n"
997 " In case of service registers -- ioctl arguments"
999 " Their amount depends on specific ioctl number.\n"
1000 " See service routines (those are with __SRV__"
1002 " for more details on parameter amount.\n\n"
1003 " For example, if this is a repetitive r/w"
1005 " (ioctl number is SRV__REP_REG_RW) then we should"
1006 " have 4 arguments,\n"
1007 " that are packed as follows:\n\n"
1008 " [0] -- ioctl number\n"
1009 " [1] -- user-space address\n"
1010 " [2] -- number of elements to r/w\n"
1011 " [3] -- element index, starting from zero\n\n"
1012 " 3 param -- check r/w bounds (1 - yes, 0 - no)\n"
1013 " valid only in case of Lynx\n"
1014 " 4 param -- repeatedly read register (1 - yes, 0 - no)\n\n\n"
1015 " Bear in mind, that r/w operation results goes diretly to"
1016 " the user space.\n"
1017 " If you want to operate on the HW registers inside the"
1019 " low-level port operation functions from"
1020 " port_ops_[linux/lynx].h like:\n"
1021 " __inb -- read a byte from a port\n"
1022 " __inw -- read a word from a port\n"
1023 " __in -- lread a long from a port\n"
1024 " __outb -- write a byte to a port\n"
1025 " __outw -- write a word to a port\n"
1026 " __outl -- write a long to a port\n"
1027 " __rep_inb -- read multiple bytes from a port into a"
1029 " __rep_inw -- read multiple words from a port into a"
1031 " __rep_inl -- read multiple longs from a port into a"
1033 " __rep_outb -- write multiple bytes to a port from a buffer\n"
1034 " __rep_outw -- write multiple words to a port from a buffer\n"
1035 " __rep_outl -- write multiple longs to a port from a"
1037 " These functions are used to r/w HW registers inside the"
1039 " Never access registers directly. Use this function to do"
1042 Translate(c_fd
, "common", "driver/getSetReg/funcDefs.c");
1044 /* ----------> first handle service registers <------------------- */
1047 TranslationSetIntNum(sizeof(time_t));
1048 TranslationSetRegType(srv_ioctl
[3].type
); /* size of DAL_CONSISTENT
1050 Translate(c_fd
, bus
, "driver/getSetReg/srvRegOps.c");
1052 /* header file starts */
1053 TranslationSetFancyString("GET_SET_REG");
1054 Translate(h_fd
, "common", "header/headerStartEnd/hsModNmStr.h");
1055 TranslationSetComment(cmt
);
1057 Translate(h_fd
, "common", "dummyTemplates/comment-multiline");
1059 /* srv regs functions declaration */
1060 Translate(h_fd
, "common", "dummyTemplates/1NewLine");
1061 TranslationSetComment("Service register operations");
1062 Translate(h_fd
, "common", "dummyTemplates/comment");
1063 TranslationSetBaseAddr("");
1064 for (cntr
= 0; cntr
< GetSrvRegNum(); cntr
++) {
1065 TranslationSetRegName(srv_ioctl
[cntr
].name
);
1066 if (srv_ioctl
[cntr
].rar
& AMRD
) { /* get register function */
1067 TranslationSetRegType("get");
1068 Translate(h_fd
, "common",
1069 "driver/getSetReg/declGetSet.h");
1071 if (srv_ioctl
[cntr
].rar
& AMWR
) { /* set register function */
1072 TranslationSetRegType("set");
1073 Translate(h_fd
, "common",
1074 "driver/getSetReg/declGetSet.h");
1078 /* ---------------> now handle all module registers <------------- */
1079 for (cntr
= 0; cntr
< numRegisters
; cntr
++) {
1080 TranslationSetRegName(registers
[cntr
].name
);
1081 TranslationSetRegType(registers
[cntr
].size
);
1082 TranslationSetRegComm(registers
[cntr
].comment
);
1083 TranslationSetRegLoop(registers
[cntr
].timeLoop
);
1084 TranslationSetFreeFormat("block%02d",
1085 registers
[cntr
].blockP
->blockID
);
1087 switch (registers
[cntr
].regSize
) {
1090 TranslationSetRegSize(8);
1094 TranslationSetRegSize(16);
1098 TranslationSetRegSize(32);
1102 TranslationSetRegSize(64);
1109 TranslationSetChar(*rsz
); /* set read/write port
1112 /* manage dataport size */
1113 if (registers
[cntr
].blockP
->blkBaseAddr
== 1)
1114 dps
= vmeInfo
->addr1
.dpSize
;
1116 dps
= vmeInfo
->addr2
.dpSize
;
1118 /* set max allowed r/w size */
1133 strDps
= "long long";
1137 fprintf(stderr
, "%s Data Port Size is NOT provided in"
1138 " the DB.\n", ERROR_MSG
);
1143 /* singularity comment string format */
1144 #define COMMENT_SINGULAR \
1145 " *\n * @warning Element size of the current register is %d bytes,\n * which is @b BIGGER than Addr[%d] DataPort Size (%d bytes).\n * Will be read/written in parts!\n *"
1147 /* if register size is bigger than Data Port Size, then
1148 register is considered to be singular and will be
1149 read/written in parts. In this case we should adjust
1150 register type and r/w port suffix to the max allowed
1151 (i.e. the data port size) */
1152 if (dps
/ 8 /*convert to bytes */ < registers
[cntr
].regSize
) {
1153 /* reg type (char, short, long) */
1154 TranslationSetRegType(strDps
);
1155 /* read/write port operation suffix */
1156 TranslationSetChar(*rsz
);
1159 /* if register size is bigger than MAX data width */
1160 if (registers
[cntr
].rar
& AMEX
) {
1161 /* ignore fake external registers */
1162 strcpy(singularity
, "Extraneous");
1163 TranslationSetComment(" *");
1165 if (registers
[cntr
].regSize
* 8 > dps
) {
1166 /* build-up singularitiy comment string
1168 snprintf(singular_comment_str
,
1169 sizeof(singular_comment_str
),
1171 registers
[cntr
].regSize
,
1172 registers
[cntr
].blockP
->blkBaseAddr
,
1174 strcpy(singularity
, "Singular");
1175 TranslationSetComment(singular_comment_str
);
1177 strcpy(singularity
, "Normal");
1178 TranslationSetComment(" *");
1182 TranslationSetFancyString(singularity
);
1184 /* if this register is a scalar, fifo or an array */
1185 if (registers
[cntr
].depth
<= 1)
1186 strcpy(accessType
, "scalar");
1188 strcpy(accessType
, "array");
1190 /* generate get/set methods depending on the register's
1192 switch (registers
[cntr
].rar
) {
1193 case AMWR
: /* 'w' write-only reg */
1195 Translate(c_fd
, "common",
1196 "driver/getSetReg/func_comment.c");
1197 Translate(c_fd
, "common", "driver/getSetReg/wo_%s.c",
1201 Translate(h_fd
, "common", "dummyTemplates/1NewLine");
1202 TranslationSetComment(registers
[cntr
].comment
);
1203 Translate(h_fd
, "common", "dummyTemplates/comment");
1204 TranslationSetBaseAddr("wo_");
1205 TranslationSetRegType("get");
1206 Translate(h_fd
, "common",
1207 "driver/getSetReg/declGetSet.h");
1208 TranslationSetBaseAddr("");
1209 TranslationSetRegType("set");
1210 Translate(h_fd
, "common",
1211 "driver/getSetReg/declGetSet.h");
1213 case AMRD
: /* 'r' read-only reg */
1215 Translate(c_fd
, "common",
1216 "driver/getSetReg/func_comment.c");
1217 Translate(c_fd
, "common", "driver/getSetReg/ro_%s.c",
1221 Translate(h_fd
, "common", "dummyTemplates/1NewLine");
1222 TranslationSetComment(registers
[cntr
].comment
);
1223 Translate(h_fd
, "common", "dummyTemplates/comment");
1224 TranslationSetBaseAddr("");
1225 TranslationSetRegType("get");
1226 Translate(h_fd
, "common",
1227 "driver/getSetReg/declGetSet.h");
1229 case (AMWR
| AMRD
): /* 'wr' read/write reg */
1231 Translate(c_fd
, "common",
1232 "driver/getSetReg/func_comment.c");
1233 Translate(c_fd
, "common", "driver/getSetReg/rw_%s.c",
1237 Translate(h_fd
, "common", "dummyTemplates/1NewLine");
1238 TranslationSetComment(registers
[cntr
].comment
);
1239 Translate(h_fd
, "common", "dummyTemplates/comment");
1240 TranslationSetBaseAddr("");
1241 TranslationSetRegType("get");
1242 Translate(h_fd
, "common",
1243 "driver/getSetReg/declGetSet.h");
1244 TranslationSetRegType("set");
1245 Translate(h_fd
, "common",
1246 "driver/getSetReg/declGetSet.h");
1248 case AMEX
: /* 'e' extraneous reg. They are always r/w */
1250 Translate(c_fd
, "common",
1251 "driver/getSetReg/func_comment.c");
1252 Translate(c_fd
, "common", "driver/getSetReg/ex_%s.c",
1256 Translate(h_fd
, "common", "dummyTemplates/1NewLine");
1257 TranslationSetComment(registers
[cntr
].comment
);
1258 Translate(h_fd
, "common", "dummyTemplates/comment");
1259 TranslationSetBaseAddr("ex_");
1260 TranslationSetRegType("get");
1261 Translate(h_fd
, "common",
1262 "driver/getSetReg/declGetSet.h");
1263 TranslationSetRegType("set");
1264 Translate(h_fd
, "common",
1265 "driver/getSetReg/declGetSet.h");
1270 } /* end of 'for(cntr = 0; cntr < numRegisters; cntr++)' */
1273 TranslationSetFancyString("GET_SET_REG");
1274 Translate(h_fd
, "common", "header/headerStartEnd/heModNmStr.h");
1281 * @brief Generates src code and header files that are common to all
1286 * It includes header files, libraries and installation/deinstallation
1291 void BuildGeneralCode()
1293 char *bus
= TranslationGetBus(); /* 'VME' or 'DRM' */
1295 printf("Building general header files for '%s' modules.\n", bus
);
1296 BuildGeneralHeaderFiles();
1298 printf("Building general libraries for '%s' modules.\n", bus
);
1299 BuildGeneralLibraries();
1301 printf("Building general install program for '%s' modules.\n", bus
);
1302 BuildGeneralInstallProgram();
1304 printf("Building general Makefiles for '%s' modules.\n", bus
);
1305 BuildGeneralMakefiles();
1307 /* instantiate scripts */
1308 printf("Instantiate supplementary scripts.\n");
1309 BuildGeneralScripts();
1313 * @brief Generates files and directories, intended for user intervention.
1317 * These are so-called <E>user entry points</E>. This is a user part of the
1318 * driver. User is allowed to modify this code if he wants to implement his
1319 * own code. There are several entry points. They are in the driver/simulator,
1320 * in the test program, in the library and in the installation program.
1324 void BuildUserPartDrvrCode()
1329 system
= TranslationGetModName();
1331 /* 0x0 build user entry points and header files for the driver */
1332 /* c-file for real driver */
1333 //printf("Building %s driver's user-defined entry poins.\n", system);
1334 TranslationSetDriverType("DRVR");
1335 TranslationSetFancyString("Drvr");
1336 TranslationSetChar('D');
1337 file
= OpenFile(DRIVER_FT
, LOC_DRVR
, "%s/%s.c", LOCAL_USER_DIR
,
1338 USER_SUBWORD_LEXEME
);
1339 Translate(file
, "common", "driver/userPart/uepHead.c");
1340 Translate(file
, "common", "driver/isr.c"); /* generate empty ISR */
1341 Translate(file
, "common", "driver/userPart/uepFoot.c");
1344 /* h-file for real driver */
1345 file
= OpenFile(DRIVER_FT
, LOC_INCL
, "%s.h", USER_SUBWORD_LEXEME
);
1346 Translate(file
, "common", "driver/userPart/uep.h");
1349 /* c-file for driver simulator */
1350 //printf("Building %s simulator's user-defined entry poins.\n", system);
1351 TranslationSetDriverType("SIM");
1352 TranslationSetFancyString("Sim");
1353 TranslationSetChar('S');
1354 file
=OpenFile(SIM_FT
, LOC_DRVR
, "%s/%s.c", LOCAL_USER_DIR
,
1355 USER_SUBWORD_LEXEME
);
1356 Translate(file
, "common", "driver/userPart/uepHead.c");
1357 Translate(file
, "common", "driver/isr.c"); /* generate empty ISR */
1358 Translate(file
, "common", "driver/userPart/uepFoot.c");
1361 /* h-file for driver simulator */
1362 file
= OpenFile(SIM_FT
, LOC_INCL
, "%s.h", USER_SUBWORD_LEXEME
);
1363 Translate(file
, "common", "driver/userPart/uep.h");
1366 /* add 'readme' file */
1367 file
= OpenFile(EXACT_FT
, LOC_DRVR
, "%s/README.1ST", LOCAL_USER_DIR
);
1368 Translate(file
, "common", "driver/userPart/warnTemplate.txt");
1371 /* Driver/Simulator version files */
1372 BuildVersionFiles(DRIVER_FT
| SIM_FT
);
1374 /* 0x1 now build user entry points in the test programm */
1375 //printf("Building %s files for user-defined test program.\n", system);
1376 file
= OpenFile(COMMON_FT
, LOC_FCLTY
, "%s/%sTest.c", LOCAL_USER_DIR
,
1377 USER_SUBWORD_LEXEME
);
1378 Translate(file
, "common", "testProg/common/userTest.c");
1381 file
= OpenFile(COMMON_FT
, LOC_FCLTY
, "%s/%sTest.h", LOCAL_USER_DIR
,
1382 USER_SUBWORD_LEXEME
);
1383 Translate(file
, "common", "testProg/common/userTest.h");
1386 /* 0x2 now build user-defined library framework */
1387 //printf("Building %s files for user-defined access library.\n", system);
1388 file
= OpenFile(COMMON_FT
, LOC_LIB
, "%s/%sAccess.c", LOCAL_USER_DIR
,
1389 USER_SUBWORD_LEXEME
);
1390 Translate(file
, "common", "lib/usrAccess/userDefinedAccess.c");
1393 file
= OpenFile(COMMON_FT
, LOC_INCL
, "%sAccess.h", USER_SUBWORD_LEXEME
);
1394 Translate(file
, "common", "lib/usrAccess/userDefinedAccess.h");
1397 /* 0x3 Install program entry point */
1398 file
= OpenFile(EXACT_FT
, LOC_INST
, "%s/install-so.c", LOCAL_USER_DIR
);
1399 Translate(file
, "common", "install/usr-install-so.c");
1404 * @brief Generates filename based on directory name, filename itself and file
1407 * @param type -- Driver, Simulator, common or exact
1408 * @param root -- full directory path
1409 * @param name -- filename
1410 * @param ext -- file extension (i.e. '.h' '.c' etc.)
1411 * @param ret -- where to put the results (if not NULL)
1413 * It also takes in account if it is a driver or driver simulator.\n
1414 * For example if @e type is @b SIM_FT, @b root is @b $HOME/tmp, @e name is
1415 * @b Myname and @e ext is @b .h, than generated filename will be
1416 * @b "$HOME/tmp/<sys_lower>MynameSim.h".\n
1417 * If @e type is @b EXACT_FT than it just generates file with name @b name
1418 * without taking in account if this is a drvr or sim.
1420 * @return Generated filename.
1422 char *GenerateFilename(FILETYPE type
, char *root
, char *name
, char *ext
,
1425 static char fn
[MAXPATHLEN
];
1427 if (type
== DRIVER_FT
) /* driver */
1428 snprintf(fn
, MAXPATHLEN
, "%s/%s%sDrvr%s", root
,
1429 TranslationGetSysLower(), name
, ext
);
1430 else if (type
== SIM_FT
) /* driver simulator */
1431 snprintf(fn
, MAXPATHLEN
, "%s/%s%sSim%s", root
,
1432 TranslationGetSysLower(), name
, ext
);
1433 else if (type
== COMMON_FT
) /* common for driver and simulator */
1434 snprintf(fn
, MAXPATHLEN
, "%s/%s%s%s", root
,
1435 TranslationGetSysLower(), name
, ext
);
1436 else /* file with exact given name
1437 (i.e. type == EXACT_FT) */
1438 snprintf(fn
, MAXPATHLEN
, "%s/%s", root
, name
);
1441 printf("%s(): Generated filename is-> %s\n", __FUNCTION__
, fn
);
1453 * @brief Create version files for real and simulator driver.
1455 * @param ft -- what to build
1459 static void BuildVersionFiles(FILETYPE ft
)
1463 if (ft
& DRIVER_FT
) {
1464 TranslationSetDriverType("DRVR");
1465 TranslationSetFancyString("Driver");
1466 file
= OpenFile(DRIVER_FT
, LOC_INCL
, "%s.h", "Version");
1467 Translate(file
, "common", "driver/userPart/uepVers.h");
1472 TranslationSetDriverType("SIM");
1473 TranslationSetFancyString("Simulator");
1474 file
= OpenFile(SIM_FT
, LOC_INCL
, "%s.h", "Version");
1475 Translate(file
, "common", "driver/userPart/uepVers.h");
1481 * @brief Returns directory name for shared source code of VME/PCI buses.
1485 * @return Shared source code directory name (GENERAL_DIR).
1487 static char *GetGeneralSrcDir()
1489 static char *shDir
= NULL
;
1490 char *mid
; /* master install dir */
1492 if (shDir
) /* directory is already created, so return */
1495 mid
= get_mid(NULL
);
1496 shDir
= (char *)calloc((strlen(mid
) + strlen(GENERAL_DIR
) + 2),
1498 sprintf(shDir
, "%s/%s", mid
, GENERAL_DIR
);
1500 if (MakeSafeDir(shDir
) == -DRIVER_GEN_BAD
)
1501 exit(EXIT_FAILURE
); /* 1 */
1507 * @brief local driver diectory name container.
1511 * @return local driver diectory name (LOCAL_DRVR_DIR).
1513 static char *GetLocalDrvrDir()
1515 static char *drvrDir
= NULL
;
1516 char *cmd
; /* current module directory */
1518 if (drvrDir
) /* directory is already created, so return */
1521 /* directory is not created yet. So DO it. */
1522 cmd
= get_msd(NULL
);
1523 drvrDir
= (char *)calloc((strlen(cmd
) + strlen(LOCAL_DRVR_DIR
) + 2),
1525 sprintf(drvrDir
, "%s/%s", cmd
, LOCAL_DRVR_DIR
);
1527 if (MakeSafeDir(drvrDir
) == -DRIVER_GEN_BAD
)
1528 exit(EXIT_FAILURE
); /* 1 */
1534 * @brief local facility directory name container.
1538 * @return local facility directory name (LOCAL_FCLTY_DIR).
1540 static char *GetLocalFcltyDir()
1542 static char *fcltyDir
= NULL
;
1543 char *cmd
; /* current module directory */
1545 if (fcltyDir
) /* directory is already created, so return */
1548 /* directory is not created yet. So DO it. */
1549 cmd
= get_msd(NULL
);
1550 fcltyDir
= (char *)calloc((strlen(cmd
) + strlen(LOCAL_FCLTY_DIR
) + 2),
1552 sprintf(fcltyDir
, "%s/%s", cmd
, LOCAL_FCLTY_DIR
);
1554 if (MakeSafeDir(fcltyDir
) == -DRIVER_GEN_BAD
)
1555 exit(EXIT_FAILURE
); /* 1 */
1561 * @brief local include directory name container.
1565 * @return local include directory name (LOCAL_INCL_DIR).
1567 static char *GetLocalInclDir()
1569 static char *inclDir
= NULL
;
1570 char *cmd
; /* current module directory */
1572 if (inclDir
) /* directory is already created, so return */
1575 /* directory is not created yet. So DO it. */
1576 cmd
= get_msd(NULL
);
1577 inclDir
= (char *)calloc((strlen(cmd
) + strlen(LOCAL_INCL_DIR
) + 2),
1579 sprintf(inclDir
, "%s/%s", cmd
, LOCAL_INCL_DIR
);
1581 if (MakeSafeDir(inclDir
) == -DRIVER_GEN_BAD
)
1582 exit(EXIT_FAILURE
); /* 1 */
1588 * @brief local library directory name container.
1592 * @return local library directory name (LOCAL_LIB_DIR).
1594 static char *GetLocalLibDir()
1596 static char *libDir
= NULL
;
1597 char *cmd
; /* current module directory */
1599 if (libDir
) /* directory is already created, so return */
1602 /* directory is not created yet. So DO it. */
1603 cmd
= get_msd(NULL
);
1604 libDir
= (char *)calloc((strlen(cmd
) + strlen(LOCAL_LIB_DIR
) + 2),
1606 sprintf(libDir
, "%s/%s", cmd
, LOCAL_LIB_DIR
);
1608 if (MakeSafeDir(libDir
) == -DRIVER_GEN_BAD
)
1609 exit(EXIT_FAILURE
); /* 1 */
1615 * @brief installation entry point directory name container.
1619 * @return installation directory name (LOCAL_INST_DIR).
1621 static char *GetLocalInstDir()
1623 static char *instDir
= NULL
;
1624 char *cmd
; /* current module directory */
1626 if (instDir
) /* directory is already created, so return */
1629 /* directory is not created yet. So DO it. */
1630 cmd
= get_msd(NULL
);
1631 instDir
= (char *)calloc((strlen(cmd
) + strlen(LOCAL_INST_DIR
) + 2),
1633 sprintf(instDir
, "%s/%s", cmd
, LOCAL_INST_DIR
);
1635 if (MakeSafeDir(instDir
) == -DRIVER_GEN_BAD
)
1636 exit(EXIT_FAILURE
); /* 1 */
1642 * @brief Creates directory named @e dirName
1644 * @param dirName -- directory name
1646 * @return -DRIVER_GEN_BAD - in case of error.
1647 * @return DRIVER_GEN_OK - if directory is created.
1648 * @return DRIVER_GEN_EXIST - if directory already exist.
1650 rstat
MakeSafeDir(char *dirName
)
1656 return DRIVER_GEN_BAD
;
1658 if (stat(dirName
, &status
)) { /* directory doesn't exist - so create */
1659 umask(0002); /* set tmp mask for dir creation */
1660 if (mkdir(dirName
, 0777)) {
1662 return DRIVER_GEN_BAD
;
1664 ret
= DRIVER_GEN_OK
;
1665 } else /* directory already exist */
1666 ret
= DRIVER_GEN_EXIST
;
1669 printf("%s() Created directory name is: %s\n", __func__
, dirName
);
1678 * @param registers -- register description
1679 * @param numRegisters -- register amount
1683 static void BuildTestProgHFile(RegisterDef_t
* registers
, int numRegisters
)
1686 int endOfBlock
= FALSE
;
1687 int i
, count
= 0, blockcntr
= 0, exNum
= 0, woNum
= 0;
1690 tstFileH
= OpenFile(COMMON_FT
, LOC_FCLTY
, "Test.h");
1692 /* Generate the first portion of the test program */
1693 TranslationSetFreeFormat("%s", DG_INC_DIR
);
1694 Translate(tstFileH
, "common", "testProg/common/headerHead.h");
1696 /* Generate the '*NUM_REGISTERS' constants, there
1697 should be one for each block that has been defined. */
1699 for (i
= 0; i
< numRegisters
; i
++) {
1701 if (i
== numRegisters
- 1)
1703 else if (registers
[i
].blockP
->blockID
!=
1704 registers
[i
+ 1].blockP
->blockID
)
1710 blockcntr
++; /* block counter */
1711 TranslationSetFancyNum(registers
[i
].blockP
->blockID
);
1712 TranslationSetPlainNum(count
);
1713 Translate(tstFileH
, "common",
1714 "testProg/common/numReg.h");
1717 if (registers
[i
].rar
== AMEX
)
1719 if (registers
[i
].rar
== AMWR
)
1723 /* Generate tentative function decls. to suppess any
1724 possible warnings */
1725 TranslationSetPlainNum(exNum
);
1726 TranslationSetRegDepth(GetSrvRegNum());
1727 TranslationSetPrecision(woNum
);
1728 Translate(tstFileH
, "common", "testProg/common/tentativeDecl.h");
1729 Translate(tstFileH
, "common", "testProg/serviceMenuHead.h");
1730 Translate(tstFileH
, "common", "testProg/common/extraneousMenuHead.h");
1731 Translate(tstFileH
, "common", "testProg/writeOnlyMenuHead.h");
1732 for (i
= 0; i
< blockcntr
; i
++) {
1733 TranslationSetFancyNum(i
);
1734 Translate(tstFileH
, "common",
1735 "testProg/common/blockMenuHead.h");
1738 Translate(tstFileH
, "common", "testProg/common/headerFoot.h");
1743 * @brief Generates the first portion of the driver's test program.
1745 * @param registers -- register description
1746 * @param numRegisters -- register amount
1747 * @param testFile -- open file descriptor
1749 * Namely the #includes, #defines and the arrays of strings containing
1750 * register comments.
1754 static void BuildTestProgConsts(RegisterDef_t
* registers
, int numRegisters
,
1757 int endOfBlock
= FALSE
;
1761 Translate(testFile
, "common", "testProg/common/testHead.c");
1763 /*------------------------------------------------------------------
1764 00. Generate the register comments string arrays. There should be
1765 an array of string for each defined block
1766 -----------------------------------------------------------------*/
1768 for (i
= 0; i
< numRegisters
; i
++)
1769 if (registers
[i
].rar
!= AMEX
) {
1770 /* exclude extraneous registers */
1771 TranslationSetFancyNum(registers
[i
].blockP
->blockID
);
1772 TranslationSetRegName(registers
[i
].name
);
1773 TranslationSetRegComm(registers
[i
].comment
);
1775 /* If we've just ended a block then this must be
1776 the start of a new one */
1778 Translate(testFile
, "common",
1779 "testProg/common/blockDefHead.c");
1780 Translate(testFile
, "common",
1781 "testProg/common/regData.c");
1783 /* Is this the end of a block? */
1784 if (i
== numRegisters
- 1)
1786 else if (registers
[i
].blockP
->blockID
!=
1787 registers
[i
+ 1].blockP
->blockID
)
1793 Translate(testFile
, "common",
1794 "dummyTemplates/endOfBraces");
1797 /*----------------------------------------------------------------
1798 01. Generate the comments string for the extraneous registers.
1799 ----------------------------------------------------------------*/
1800 Translate(testFile
, "common", "testProg/common/extraneousDefHead.c");
1801 for (i
= 0; i
< numRegisters
; i
++)
1802 if (registers
[i
].rar
== AMEX
) { /* is it is extraneous? */
1803 TranslationSetRegName(registers
[i
].name
);
1804 TranslationSetRegComm(registers
[i
].comment
);
1805 Translate(testFile
, "common",
1806 "testProg/common/regData.c");
1808 Translate(testFile
, "common", "dummyTemplates/endOfBraces");
1810 /*----------------------------------------------------------------
1811 02. Generate the comments string for the writeOnly registers.
1812 ----------------------------------------------------------------*/
1813 Translate(testFile
, "common", "testProg/writeOnlyDefHead.c");
1814 for (i
= 0; i
< numRegisters
; i
++)
1815 if (registers
[i
].rar
== AMWR
) { /* is it is writeOnly? */
1816 TranslationSetRegName(registers
[i
].name
);
1817 TranslationSetRegComm(registers
[i
].comment
);
1818 Translate(testFile
, "common",
1819 "testProg/common/regData.c");
1821 Translate(testFile
, "common", "dummyTemplates/endOfBraces");
1823 /*-------------------------------------------------------------
1824 03. Generate the comments string for Service Registers.
1825 -------------------------------------------------------------*/
1826 Translate(testFile
, "common", "testProg/serviceDefHead.c");
1827 for (i
= 0; i
< GetSrvRegNum(); i
++) {
1828 TranslationSetRegName(srv_ioctl
[i
].name
);
1829 TranslationSetRegComm(srv_ioctl
[i
].comment
);
1830 Translate(testFile
, "common", "testProg/common/regData.c");
1832 Translate(testFile
, "common", "dummyTemplates/endOfBraces");
1836 * @brief Generate the last portion of the driver's test program.
1838 * @param registers -- register description
1839 * @param blocks -- block description
1840 * @param numRegisters -- register amount
1841 * @param testFile -- open file descriptor
1843 * It produces a sub menu for each of the defined blocks and for the extraneous
1848 static void BuildTestProgSubMenus(RegisterDef_t
* registers
,
1849 BlockDef_t
* blocks
, int numRegisters
,
1852 int i
, j
, count
, blockStart
, endOfBlock
;
1856 /*=================00. Generate WriteOnly Registers sub menu.==============*/
1857 Translate(testFile
, "common", "testProg/writeOnlyMenuHead.c");
1858 if (!HasWriteOnly(registers
, numRegisters
))
1859 Translate(testFile
, "common", "testProg/writeOnlyNO.c");
1861 /* Add a menu item for each extraneous variable that's
1863 Translate(testFile
, "common", "testProg/common/menuHead.c");
1864 count
= TST_PROG_SUB_MENU_FIRST_ENTRY
;
1866 for (i
= 0; i
< numRegisters
; i
++)
1867 if (registers
[i
].rar
== AMWR
) {
1868 /* is it is writeOnly reg? */
1869 TranslationSetRegName(registers
[i
].name
);
1872 TranslationSetPlainNum(count
++);
1873 Translate(testFile
, "common",
1874 "testProg/common/menuReadEntry.c");
1877 Translate(testFile
, "common", "testProg/common/menuFoot.c");
1878 Translate(testFile
, "common", "testProg/writeOnlyCaseHead.c");
1879 count
= TST_PROG_SUB_MENU_FIRST_ENTRY
;
1881 for (i
= 0; i
< numRegisters
; i
++)
1882 if (registers
[i
].rar
== AMWR
) {
1883 /* is it is writeOnly? */
1884 TranslationSetRegId(registers
[i
].upperName
);
1887 TranslationSetPlainNum(count
++);
1888 TranslationSetFancyString("Get");
1889 Translate(testFile
, "common",
1890 "testProg/common/caseGetSet.c");
1892 Translate(testFile
, "common", "testProg/common/caseEnd.c");
1895 /*=================01. Generate Extraneous Variable sub menu.==============*/
1896 Translate(testFile
, "common", "testProg/common/extraneousMenuHead.c");
1897 if (!HasExtraneous(registers
, numRegisters
))
1898 /* If there were not any extraneous variables then generate
1899 code to alert the test program's user that there aren't any
1900 extra variables. If there were extraneous variables then
1901 produce the case statments that should accompany the menu
1903 Translate(testFile
, "common", "testProg/common/extraneousNO.c");
1905 /* Add a menu item for each extraneous variable that's been
1907 Translate(testFile
, "common", "testProg/common/menuHead.c");
1908 count
= TST_PROG_SUB_MENU_FIRST_ENTRY
;
1910 for (i
= 0; i
< numRegisters
; i
++)
1911 if (registers
[i
].rar
== AMEX
) {
1912 /* is it is extraneous? */
1913 TranslationSetRegName(registers
[i
].name
);
1916 TranslationSetPlainNum(count
++);
1917 Translate(testFile
, "common",
1918 "testProg/common/menuReadEntry.c");
1921 TranslationSetPlainNum(count
++);
1922 Translate(testFile
, "common",
1923 "testProg/common/menuWriteEntry.c");
1925 Translate(testFile
, "common", "testProg/common/menuFoot.c");
1926 Translate(testFile
, "common",
1927 "testProg/common/extraneousCaseHead.c");
1928 count
= TST_PROG_SUB_MENU_FIRST_ENTRY
;
1930 for (i
= 0; i
< numRegisters
; i
++)
1931 if (registers
[i
].rar
== AMEX
) {
1932 /* is it is extraneous? */
1933 TranslationSetRegId(registers
[i
].upperName
);
1936 TranslationSetPlainNum(count
++);
1937 TranslationSetFancyString("Get");
1938 Translate(testFile
, "common",
1939 "testProg/common/caseGetSet.c");
1942 TranslationSetPlainNum(count
++);
1943 TranslationSetFancyString("Set");
1944 Translate(testFile
, "common",
1945 "testProg/common/caseGetSet.c");
1947 Translate(testFile
, "common", "testProg/common/caseEnd.c");
1950 /*=========02. Generate Service Registers sub menu.====================*/
1951 Translate(testFile
, "common", "testProg/serviceMenuHead.c");
1952 Translate(testFile
, "common", "testProg/common/menuHead.c");
1953 count
= TST_PROG_SUB_MENU_FIRST_ENTRY
;
1955 for (i
= 0; i
< GetSrvRegNum(); i
++) {
1956 TranslationSetRegName(srv_ioctl
[i
].name
);
1957 switch (srv_ioctl
[i
].rar
) {
1958 case AMRD
: /* 'r' */
1959 TranslationSetPlainNum(count
++);
1960 Translate(testFile
, "common",
1961 "testProg/common/menuReadEntry.c");
1963 case AMWR
: /* 'w' */
1964 TranslationSetPlainNum(count
++);
1965 Translate(testFile
, "common",
1966 "testProg/common/menuWriteEntry.c");
1968 case (AMRD
| AMWR
): /* 'rw' */
1969 TranslationSetPlainNum(count
++);
1970 Translate(testFile
, "common",
1971 "testProg/common/menuReadEntry.c");
1972 TranslationSetPlainNum(count
++);
1973 Translate(testFile
, "common",
1974 "testProg/common/menuWriteEntry.c");
1977 /* it's not an error, just this service register
1982 Translate(testFile
, "common", "testProg/common/menuFoot.c");
1983 Translate(testFile
, "common", "testProg/serviceCaseHead.c");
1984 count
= TST_PROG_SUB_MENU_FIRST_ENTRY
;
1986 for (i
= 0; i
< GetSrvRegNum(); i
++) {
1987 TranslationSetRegId(srv_ioctl
[i
].name
);
1988 switch (srv_ioctl
[i
].rar
) {
1989 case AMRD
: /* 'r' */
1990 TranslationSetPlainNum(count
++);
1991 TranslationSetFancyString("Get");
1992 Translate(testFile
, "common",
1993 "testProg/common/caseGetSet.c");
1995 case AMWR
: /* 'w' */
1996 TranslationSetPlainNum(count
++);
1997 TranslationSetFancyString("Set");
1998 Translate(testFile
, "common",
1999 "testProg/common/caseGetSet.c");
2001 case (AMRD
| AMWR
): /* 'rw' */
2002 TranslationSetPlainNum(count
++);
2003 TranslationSetFancyString("Get");
2004 Translate(testFile
, "common",
2005 "testProg/common/caseGetSet.c");
2007 TranslationSetPlainNum(count
++);
2008 TranslationSetFancyString("Set");
2009 Translate(testFile
, "common",
2010 "testProg/common/caseGetSet.c");
2013 /* it's not an error, just this service register
2018 Translate(testFile
, "common", "testProg/common/caseEnd.c");
2020 /*=====03. Now generate sub menus for each of the defined blocks.==========*/
2023 for (i
= 0; i
< numRegisters
; i
++)
2024 if (registers
[i
].rar
!= AMEX
) { /* skip extraneous registers */
2026 TranslationSetFancyNum(registers
[i
].blockP
->
2028 TranslationSetPlainNum(registers
[i
].blockP
->
2030 Translate(testFile
, "common",
2031 "testProg/common/blockMenuHead.c");
2032 Translate(testFile
, "common",
2033 "testProg/common/menuHead.c");
2034 count
= TST_PROG_SUB_MENU_FIRST_ENTRY
;
2037 TranslationSetRegName(registers
[i
].name
);
2038 switch (registers
[i
].rar
) {
2039 case AMRD
: /* 'r' */
2040 TranslationSetPlainNum(count
++);
2041 Translate(testFile
, "common",
2042 "testProg/common/menuReadEntry.c");
2044 case AMWR
: /* 'w' */
2045 TranslationSetPlainNum(count
++);
2046 Translate(testFile
, "common",
2047 "testProg/common/menuWriteEntry.c");
2049 case (AMWR
| AMRD
): /* 'rw' */
2050 TranslationSetPlainNum(count
++);
2051 Translate(testFile
, "common",
2052 "testProg/common/menuReadEntry.c");
2054 TranslationSetPlainNum(count
++);
2055 Translate(testFile
, "common",
2056 "testProg/common/menuWriteEntry.c");
2063 if (i
== numRegisters
- 1)
2065 else if (registers
[i
].blockP
->blockID
!=
2066 registers
[i
+ 1].blockP
->blockID
)
2071 if (endOfBlock
) { /* now 'switch' can be generated */
2072 Translate(testFile
, "common",
2073 "testProg/common/menuFoot.c");
2074 Translate(testFile
, "common",
2075 "testProg/common/blockCaseHead.c");
2076 count
= TST_PROG_SUB_MENU_FIRST_ENTRY
;
2078 for (j
= blockStart
; j
<= i
; j
++) {
2079 TranslationSetRegId(registers
[j
].
2081 switch (registers
[j
].rar
) {
2082 case AMRD
: /* 'r' */
2083 TranslationSetPlainNum(count
++);
2084 TranslationSetFancyString
2086 Translate(testFile
, "common",
2090 case AMWR
: /* 'w' */
2091 TranslationSetPlainNum(count
++);
2092 TranslationSetFancyString
2094 Translate(testFile
, "common",
2098 case (AMWR
| AMRD
): /* 'rw' */
2099 TranslationSetPlainNum(count
++);
2100 TranslationSetFancyString
2102 Translate(testFile
, "common",
2106 TranslationSetPlainNum(count
++);
2107 TranslationSetFancyString
2109 Translate(testFile
, "common",
2118 Translate(testFile
, "common",
2119 "testProg/common/caseEnd.c");
2125 * @brief Create major header files that are common for all VME/DRM drivers.
2127 static void BuildGeneralHeaderFiles(void)
2130 int constCounter
; /* */
2132 char *bus
= TranslationGetBus(); /* 'VME' or 'DRM' */
2134 /* set general constants */
2135 fp
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/GeneralHeader.h", DG_INC_DIR
);
2136 TranslationSetPrecision(MAX_STR
);
2137 TranslationSetDDDNum(MIN_STR
);
2138 TranslationSetPlainNum(NAME_LEN
);
2139 TranslationSetRegDepth(MAX_REG
);
2140 TranslationSetIntNum(MAX_BLK
);
2141 TranslationSetExtraNum(NO_ADDRESS
);
2142 TranslationSetHexNum(NO_LUN
);
2143 Translate(fp
, "common", "header/generalHeader.h");
2146 /* header for driver and simulator. Differs for VME/PCI buses. */
2147 fp
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/ModuleHeader.h", DG_INC_DIR
);
2148 Translate(fp
, bus
, "header/generalHeader.h");
2151 /* register description is placed here */
2152 fp
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/RegDesc.h", DG_INC_DIR
);
2153 Translate(fp
, "common", "header/regDesc.h");
2156 /* seed Linux Kernel List */
2157 fp
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/lklist.h", DG_INC_DIR
);
2158 Translate(fp
, "common", "header/lklist.h");
2161 /* VMEbus Address Modifier Codes */
2162 fp
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/vme_am.h", DG_INC_DIR
);
2163 Translate(fp
, "../include", "vme_am.h");
2166 /* port operations for Lynx */
2167 fp
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/port_ops_lynx.h", DG_INC_DIR
);
2168 Translate(fp
, "common", "header/port_ops_lynx.h");
2171 /* port operations for Linux */
2172 fp
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/port_ops_linux.h", DG_INC_DIR
);
2173 Translate(fp
, "common", "header/port_ops_linux.h");
2176 /* extra swap operations for Linux */
2177 fp
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/swab-extra-linux.h",
2179 Translate(fp
, "common", "header/swab-extra-linux.h");
2182 /* service registers ioctl numbers */
2183 fp
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/ServiceRegIoctl.h",
2185 Translate(fp
, "common", "header/srvHead.h");
2186 TranslationSetFancyString("IOCTL_BASE"); /* setup base number for the
2187 service ioctl numbers */
2189 for (cntr
= 0, constCounter
= 0; cntr
< GetSrvRegNum(); cntr
++) {
2190 switch (srv_ioctl
[cntr
].rar
) {
2191 case AMRD
: /* 'r' */
2192 TranslationSetPlainNum(constCounter
++);
2193 TranslationSetIoctlConst("GET", srv_ioctl
[cntr
].name
);
2194 Translate(fp
, "common", "header/ioctlConst.h");
2196 case AMWR
: /* 'w' */
2197 TranslationSetPlainNum(constCounter
++);
2198 TranslationSetIoctlConst("SET", srv_ioctl
[cntr
].name
);
2199 Translate(fp
, "common", "header/ioctlConst.h");
2201 case (AMWR
| AMRD
): /* 'rw' */
2202 TranslationSetPlainNum(constCounter
++);
2203 TranslationSetIoctlConst("GET", srv_ioctl
[cntr
].name
);
2204 Translate(fp
, "common", "header/ioctlConst.h");
2206 TranslationSetPlainNum(constCounter
++);
2207 TranslationSetIoctlConst("SET", srv_ioctl
[cntr
].name
);
2208 Translate(fp
, "common", "header/ioctlConst.h");
2211 /* special srv register that has ioctl entry,
2212 but it's not a 'r/w' register */
2213 TranslationSetPlainNum(constCounter
++);
2214 TranslationSetIoctlConst("", srv_ioctl
[cntr
].name
);
2215 Translate(fp
, "common", "header/ioctlConst.h");
2220 TranslationSetPlainNum(constCounter
);
2221 Translate(fp
, "common", "header/srvFoot.h");
2224 /* service registers ID enum */
2225 fp
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/ServiceRegId.h", DG_INC_DIR
);
2226 Translate(fp
, "common", "header/srvIdHead.h");
2228 for (cntr
= 0, constCounter
= 0; cntr
< GetSrvRegNum(); cntr
++) {
2229 TranslationSetRegId(srv_ioctl
[cntr
].name
);
2230 TranslationSetRegComm(srv_ioctl
[cntr
].comment
);
2231 TranslationSetFancyString(rar2mode(srv_ioctl
[cntr
].rar
));
2232 TranslationSetDummyString(itoa(constCounter
++, 10));
2233 Translate(fp
, "common", "header/regIdEnumIndexed.h");
2236 /* set last service regID description */
2237 TranslationSetRegName(srv_ioctl
[cntr
].name
);
2238 TranslationSetRegComm(srv_ioctl
[cntr
].comment
);
2239 TranslationSetDummyString(itoa(constCounter
, 10));
2240 Translate(fp
, "common", "header/srvIdFoot.h");
2245 * @brief Generate general libraries source code, wich are @b DriverAccess,
2246 * @b Ioconfig and @b extra-lynx
2250 * DriverAccess library enables user to use @e DaGetElement(),
2251 * @e DaSetElement() and many other functions for register accessing.
2253 * Ioconfig library enables user to access driver by means of @e ioconfig
2254 * calls, that uses a direct memory access mechanism for accessing.
2256 * xtra-lynx -- imports such handy functions as vsnprintf, asprintf etc...
2257 * into user-space apps.
2261 static void BuildGeneralLibraries()
2264 char *bus
= TranslationGetBus(); /* 'VME' or 'DRM' */
2265 char *tstr
= ctime(&mod_creation_time
);
2267 tstr
[strlen(tstr
) - 1] = 0; /* get rid of '\n' */
2269 /* driverAccess library source code */
2270 /* generate '.h' file */
2271 fd
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/dal.h", DG_INC_DIR
);
2272 Translate(fd
, bus
, "lib/drvrAccess/DrvrAccess.h");
2275 /* generate '.c' files */
2276 fd
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/dal.c", DAL_DIR
);
2278 /* set DAL generation time */
2279 TranslationSetHexNum(mod_creation_time
);
2280 TranslationSetComment(tstr
);
2283 Translate(fd
, bus
, "lib/drvrAccess/DrvrAccess.c");
2286 /* Linux DMA support */
2287 fd
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/dma.c", DAL_DIR
);
2288 Translate(fd
, bus
, "lib/drvrAccess/dma.c");
2291 fd
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/swa.h", DG_INC_DIR
);
2292 Translate(fd
, bus
, "lib/drvrAccess/swa.h");
2296 /* mmap access for Lynx */
2297 fd
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/IoconfAccess.c", DAL_DIR
);
2298 Translate(fd
, bus
, "lib/drvrAccess/ioconf.c");
2301 /* xtra-lynx library -- handy function for lynx user-space */
2302 fd
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/lynx-extra.c", DAL_DIR
);
2303 Translate(fd
, bus
, "lib/drvrAccess/lynx-extra.c");
2308 * @brief Build Device driver installation/uninstallation program source code.
2314 static void BuildGeneralInstallProgram()
2317 char *bus
= TranslationGetBus(); /* 'VME' or 'DRM' */
2319 /* generate install program '.h' file */
2320 fd
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/modinst.h", DG_INC_DIR
);
2321 Translate(fd
, bus
, "installProg/modinst.h");
2324 /* generate install program '.c' file */
2325 fd
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/modinst.c", INST_RM_DIR
);
2326 Translate(fd
, bus
, "installProg/modinst.c");
2329 /* generate deinstall program '.h' file */
2330 fd
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/moduninst.h", DG_INC_DIR
);
2331 Translate(fd
, bus
, "installProg/moduninst.h");
2334 /* generate deinstall program '.c' file */
2335 fd
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/moduninst.c", INST_RM_DIR
);
2336 Translate(fd
, bus
, "installProg/moduninst.c");
2340 fd
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/utils.c", INST_RM_DIR
);
2341 Translate(fd
, bus
, "installProg/utils.c");
2344 fd
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/utils.h", DG_INC_DIR
);
2345 Translate(fd
, bus
, "installProg/utils.h");
2348 /* Lynx-specific utils */
2349 fd
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/utils-lynx.c", INST_RM_DIR
);
2350 Translate(fd
, bus
, "installProg/utils-lynx.c");
2353 /* Linux-specific utils */
2354 fd
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/utils-linux.c", INST_RM_DIR
);
2355 Translate(fd
, bus
, "installProg/utils-linux.c");
2358 /* Lynx API, needed for linux */
2359 fd
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/extra-linux.c", INST_RM_DIR
);
2360 Translate(fd
, bus
, "installProg/extra-linux.c");
2363 fd
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/extra-linux.h", DG_INC_DIR
);
2364 Translate(fd
, bus
, "installProg/extra-linux.h");
2369 * @brief Build-up makefiles that are located in @e general directory.
2373 * They contains install/uninstall programs, DALib and header files that are
2374 * common to all generated drivers.
2378 static void BuildGeneralMakefiles()
2383 mkfd
= OpenFile(EXACT_FT
, LOC_GENERAL
, "Makefile.base");
2384 Translate(mkfd
, "common", "makefiles/Makefile.base");
2387 /* "Which dirs to compile" Makefile */
2388 mkfd
= OpenFile(EXACT_FT
, LOC_GENERAL
, "Makefile");
2389 TranslationSetFreeFormat("%s", DG_INC_DIR
);
2390 TranslationSetString(DAL_DIR
);
2391 TranslationSetComment(INST_RM_DIR
);
2392 Translate(mkfd
, "common", "makefiles/MakefileShared");
2395 /* Include Makefile */
2396 mkfd
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/Makefile", DG_INC_DIR
);
2397 Translate(mkfd
, "common", "makefiles/includeGeneral.mk");
2400 /* Libraries Makefile */
2401 mkfd
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/Makefile", DAL_DIR
);
2403 Translate(mkfd
, "common", "makefiles/libShared.mk");
2406 /* Install program Makefile */
2407 mkfd
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/Makefile", INST_RM_DIR
);
2408 TranslationSetString(DG_INC_DIR
);
2409 Translate(mkfd
, "common", "makefiles/instProg.mk");
2412 mkfd
= OpenFile(EXACT_FT
, LOC_GENERAL
, "%s/deliver.mk", INST_RM_DIR
);
2413 Translate(mkfd
, "common", "makefiles/deliver.mk");
2424 static void BuildGeneralScripts(void)
2428 mkfd
= OpenFile(EXACT_FT
, LOC_GENERAL
, UTIL_CP_USR_PT_GLOB
);
2429 Translate(mkfd
, "common", UTIL_CP_USR_PT_GLOB
);
2430 fchmod(fileno(mkfd
), 0755); /* set new access rights */
2435 * @brief Checks if register description obtained from the data base contains
2436 * any extraneous registers.
2438 * @param registers -- register description
2439 * @param numRegisters -- register amount
2441 * @return amount of extraneous registers
2443 static int HasExtraneous(RegisterDef_t
* registers
, int numRegisters
)
2448 for (cntr
= 0; cntr
< numRegisters
; cntr
++)
2449 if (registers
[cntr
].rar
== AMEX
)
2456 * @brief Checks if register description obtained from the data base contains
2457 * any writeOnly registers.
2459 * @param registers -- register description
2460 * @param numRegisters -- register amount
2462 * @return amount of writeonly registers.
2464 static int HasWriteOnly(RegisterDef_t
* registers
, int numRegisters
)
2466 static int amount
= -1;
2471 for (i
= 0; i
< numRegisters
; i
++)
2472 if (registers
[i
].rar
== AMWR
)