[driver-gen-git] Add git library files.
[driver-gen.git] / commonGeneration.c
bloba1df6886bea434b45141cb4c6ba033920c9d5f23
1 /**
2 * @file commonGeneration.c
4 * @brief Generates driver files that are common for both, VME and PCI modules.
6 * @author Copyright (c) 2004 - 2009 CERN. Georgievskiy Yury, Alain Gagnaire
8 * @date Created on 27/02/2004
9 */
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include "driverGen.h"
13 #include "utilities.h"
15 static void BuildVersionFiles(FILETYPE);
16 static char *GetGeneralSrcDir();
17 static char *GetLocalDrvrDir();
18 static char *GetLocalFcltyDir();
19 static char *GetLocalInclDir();
20 static char *GetLocalLibDir();
21 static char *GetLocalInstDir();
22 static void BuildTestProgHFile(RegisterDef_t *, int);
23 static void BuildTestProgConsts(RegisterDef_t *, int, FILE *);
24 static void BuildTestProgSubMenus(RegisterDef_t *, BlockDef_t *, int, FILE *);
25 static void BuildGeneralHeaderFiles();
26 static void BuildGeneralLibraries();
27 static void BuildGeneralInstallProgram();
28 static void BuildGeneralMakefiles();
29 static void BuildGeneralScripts();
30 static int HasExtraneous(RegisterDef_t *, int);
31 static int HasWriteOnly(RegisterDef_t *, int);
33 /**
34 * @brief TODO. REMOVE! (Still used by drmGeneration.c module)
36 * @param numDevs --
38 * @return void
40 void BuildDescsOLD(int numDevs)
42 FILE *devDescFile;
43 FILE *simDescFile;
44 FILE *opDescFile;
45 int i;
47 devDescFile = OpenFile(DRIVER_FT, LOC_MODSRC, "INST_BI/Dev.desc");
48 simDescFile = OpenFile(SIM_FT, LOC_MODSRC, "INST_BI/Dev.desc");
49 opDescFile = OpenFile(DRIVER_FT, LOC_MODSRC, "INST_BI/.desc");
51 Translate(devDescFile, "common", "descs/devHead.desc");
52 Translate(simDescFile, "common", "descs/simHead.desc");
53 Translate(opDescFile, "common", "descs/opHead.desc");
55 for (i = 0; i < numDevs; i++) {
56 TranslationSetFancyNum(i);
57 TranslationSetPlainNum(i);
58 Translate(devDescFile, "common", "descs/devDef.desc");
59 Translate(simDescFile, "common", "descs/devDef.desc");
60 Translate(opDescFile, "common", "descs/devDef.desc");
63 fclose(devDescFile);
64 fclose(simDescFile);
65 fclose(opDescFile);
68 /**
69 * @brief Create and open for editing file with the specified name <b>name</b>
71 * @param type -- @b DRIVER_FT, @b SIM_FT, @b COMMON_FT or @b EXACT_FT
72 * @param loc -- file path
73 * @param name -- filename
74 * @param ... -- extra parameters in case if filename @e name contains
75 * conversion specification(s)
77 * - 0x0. Parameter 'name' can consist of conversion
78 * specification (e.g. '%s'), that begins with the character '%'.
79 * In this case one should provide additional parameters for each
80 * specification
81 * - 0x1. This function takes into account currently processed
82 * module type (driver or simulator). If it's a driver, than
83 * suffix 'Drvr' will be added to the generated file name. If it's
84 * simulator, than suffix 'Sim' will be added. It also can be
85 * so-called 'EXACT_FT' type In this case file is created with
86 * exact given name, without adding any specific driver or
87 * simulator prefixes or suffixes. If type is COMMON_FT than
88 * only 'driver name' preffix is added (e.g. SharedCibc), but not
89 * driver or simulator suffixes.
90 * - 0x2. Nested directories, where file should be located are
91 * created also. To denote the fact that nested dir(s) are
92 * needed - one should provide their names in the 'name' parameter
93 * (e.g. 'subdir0/subdir1.../subdirN/filename.c'). Directories
94 * subdir0, subdir1, ... subdirN will be created.
95 * - 0x3. Parameter 'loc' points out initial directory, where
96 * file should be located. See definition of type 'localtion' for
97 * more information.
99 * @e Example:\n\n
100 * Consider that driver is <b>SHARED_CIBC</b>. This means that
101 * <sys_lower> is "SharedCibc". Also consider that file name that
102 * you want to generate is 'My.c' (@e name parameter):\n
103 * type == DRIVER_FT. <filename> will be 'SharedCibcMyDrvr.c'\n
104 * type == SIM_FT. <filename> will be 'SharedCibcMySim.c'\n
105 * type == COMMON_FT. <filename> will be 'SharedCibcMy.c\n
106 * type == EXACT_FT. <filename> will be 'My.c'\n\n
107 * Depending on 'loc' (location) param, file will be build in
108 * different directories:\n
109 * <I>LOC_MASTER ~/\$(MASTER_DIR)/<filename></I>\n
110 * <I>LOC_GENERAL ~/\$(MASTER_DIR)/\$(GENERAL_DIR)/<filename></I>\n
111 * <I>LOC_MODSRC ~/\$(MASTER_DIR)/\$(DRIVER_DIRECTORY)/<filename></I>\n
112 * <I>LOC_DRVR ~/\$(MASTER_DIR)/\$(DRIVER_DIRECTORY)/driver/<filename></I>\n
113 * <I>LOC_FCLTY ~/\$(MASTER_DIR)/\$(DRIVER_DIRECTORY)/test/<filename></I>\n
114 * <I>LOC_INCL ~/\$(MASTER_DIR)/\$(DRIVER_DIRECTORY)/include/<filename></I>\n
115 * <I>LOC_LIB ~/\$(MASTER_DIR)/\$(DRIVER_DIRECTORY)/lib/<filename></I>\n
116 * <I>LOC_INST ~/\$(MASTER_DIR)/\$(DRIVER_DIRECTORY)/install/<filename></I>\n
117 * <I>LOC_EXPLICIT ~/\$(name) - NOT IMPLEMENTED YET!!! TODO
119 * @note In case of <b>LOC_EXPLICIT</b> you should provide complete directory
120 * path in the <b>name</b> parameter. Afterwards, based on the
121 * <b>type</b> parameter filename will be build.
123 * @return FILE pointer - if succeed.
124 * @return NULL - if error occurs.
126 FILE *OpenFile(FILETYPE type, location loc, char *name, ...)
128 va_list ap;
129 char inputName[MAXPATHLEN];
130 char *suffix = NULL, *prefix = NULL, *ptr;
131 int sz;
132 char *curDir;
133 char dirPath[4096];
134 char *dpPtr = dirPath;
135 char *nestDir;
136 FILE *retFd;
138 /* build-up the name first */
139 va_start(ap, name);
140 vsnprintf(inputName, sizeof(inputName), name, ap);
141 va_end(ap);
143 memset(dirPath, 0, sizeof(dirPath));
145 if (type == EXACT_FT) {
146 prefix = strdup(inputName);
147 } else {
148 if (!(suffix = rindex(inputName, '.')))
149 return (NULL); /* wrong name */
151 sz = strlen(inputName) - strlen(suffix);
152 prefix = (char *)calloc((sz + 1), sizeof(char));
153 strncpy(prefix, inputName, sz);
156 switch (loc) {
157 case LOC_MASTER:
158 ptr = get_mid(NULL);
159 break;
160 case LOC_GENERAL:
161 ptr = GetGeneralSrcDir();
162 break;
163 case LOC_MODSRC:
164 ptr = get_msd(NULL);
165 break;
166 case LOC_DRVR:
167 ptr = GetLocalDrvrDir();
168 break;
169 case LOC_FCLTY:
170 ptr = GetLocalFcltyDir();
171 break;
172 case LOC_INCL:
173 ptr = GetLocalInclDir();
174 break;
175 case LOC_LIB:
176 ptr = GetLocalLibDir();
177 break;
178 case LOC_INST:
179 ptr = GetLocalInstDir();
180 break;
181 case LOC_EXPLICIT: /* TODO */
182 break;
183 default:
184 return (NULL); /* error */
185 break;
187 strncpy(dirPath, ptr, strlen(ptr));
189 /* Check if nested directories are required */
190 if ((ptr = strrchr(prefix, '/'))) {
191 char tmpBuf[2048];
192 *ptr = 0;
193 nestDir = strdup(prefix); /* copy, to prevent corruption */
194 ptr++;
195 strcpy(tmpBuf, ptr);
196 prefix = realloc(prefix, strlen(ptr) + 1);
197 strcpy(prefix, tmpBuf);
199 dpPtr += strlen(dirPath);
200 *dpPtr = '/';
201 dpPtr++;
203 curDir = strtok(nestDir, "/");
204 while (curDir) { /* create new directories */
205 strcpy(dpPtr, curDir);
206 /* TODO. no buffer overflow check! */
207 dpPtr += strlen(curDir);
208 *dpPtr = '/';
209 dpPtr++;
210 if (MakeSafeDir(dirPath) == -DRIVER_GEN_BAD)
211 return NULL;
212 curDir = strtok(NULL, "/");
214 free(nestDir);
218 struct stat status;
219 char *final_fn =
220 GenerateFilename(type, dirPath, prefix, suffix, NULL);
222 if (!stat(final_fn, &status))
223 /* filename is already exist. We should check
224 access permission rights and change them if
225 needed (as we'll need 'w' access right) */
226 chmod(final_fn, (status.st_mode | S_IWUSR | S_IWGRP));
228 retFd = fopen(final_fn, "w");
229 free(prefix);
232 return (retFd);
236 * @brief Generate driver IOCTL numbers
238 * @param registers -- register description
239 * @param numRegisters -- register amount
240 * @param headerFile -- open header file descriptor
242 * @return void
244 void BuildIoctlConsts(RegisterDef_t * registers, int numRegisters,
245 FILE * headerFile)
247 int cntr;
248 int constCounter = 0; /* driver ioctl index */
250 TranslationReset();
252 /* Set first allowed ioctl number for the driver ioctl numbers
253 Keep the name in accordance with
254 templates/common/header/srvFoot.h! */
255 TranslationSetFancyString("_FIRST__IOCTL_");
257 for (cntr = 0; cntr < numRegisters; cntr++) {
258 switch (registers[cntr].rar) {
259 case AMRD: /* 'r' */
260 TranslationSetPlainNum(constCounter++);
261 TranslationSetIoctlConst("GET",
262 registers[cntr].upperName);
263 Translate(headerFile, "common", "header/ioctlConst.h");
264 break;
265 case AMWR: /* 'w' */
266 TranslationSetPlainNum(constCounter++);
267 TranslationSetIoctlConst("GET_HISTORY",
268 registers[cntr].upperName);
269 Translate(headerFile, "common", "header/ioctlConst.h");
271 TranslationSetPlainNum(constCounter++);
272 TranslationSetIoctlConst("SET",
273 registers[cntr].upperName);
274 Translate(headerFile, "common", "header/ioctlConst.h");
275 break;
276 case (AMWR | AMRD): /* 'rw' */
277 case AMEX: /* 'e' */
278 TranslationSetPlainNum(constCounter++);
279 TranslationSetIoctlConst("GET",
280 registers[cntr].upperName);
281 Translate(headerFile, "common", "header/ioctlConst.h");
283 TranslationSetPlainNum(constCounter++);
284 TranslationSetIoctlConst("SET",
285 registers[cntr].upperName);
286 Translate(headerFile, "common", "header/ioctlConst.h");
287 break;
288 default:
289 FATAL_ERR();
290 break;
292 } /* end of 'for' */
294 /* set first allowed user-defined ioctl number */
295 Translate(headerFile, "common", "dummyTemplates/1NewLine");
296 TranslationSetComment("First allowed number for user-defined ioctl");
297 Translate(headerFile, "common", "dummyTemplates/comment");
299 TranslationSetPlainNum(constCounter);
300 TranslationSetIoctlConst("FIRST_USR", "IOCTL");
301 Translate(headerFile, "common", "header/ioctlConst.h");
305 * @brief Generate module topology.
307 * @param type -- driver (DRIVER_FT) or simulator (SIM_FT)
308 * @param registers -- register description
309 * @param numRegisters -- register amount
310 * @param headerFile -- open header file descriptor
312 * Generate a history structure to store values that were written to writeonly
313 * registers, an extraneous structure for extra driver variables, defined by
314 * the user and a structure for each block that has been defined in the design.
316 * @return void
318 void BuildCommonBlocks(int type, RegisterDef_t * registers, int numRegisters,
319 FILE * headerFile)
321 int i;
322 int theGap; /* memory gap size betveen the registers */
323 int endOfBlock;
324 int prevFreeAddr; /* for memory gap computing */
326 TranslationReset();
328 /*--------------------------------------------------------------
329 00. Generate the driver's writeonly structure.
330 --------------------------------------------------------------*/
331 TranslationSetFreeFormat
332 ("keeps last written value of the 'write only' registers");
333 TranslationSetDummyString("");
334 Translate(headerFile, "common", "header/structHead.h");
335 for (i = 0; i < numRegisters; i++) {
336 if (registers[i].rar == AMWR) { /* Is the register writeonly? */
337 TranslationSetRegDepth(registers[i].depth);
338 TranslationSetRegType(registers[i].size);
339 TranslationSetRegName(registers[i].name);
340 if (registers[i].depth <= 1) { /* one register */
341 TranslationSetHexNum(registers[i].offset);
342 TranslationSetFreeFormat("last written value");
343 Translate(headerFile, "common",
344 "header/recordDefScalar.h");
345 } else { /* massive */
346 TranslationSetFreeFormat("last written values");
347 Translate(headerFile, "common",
348 "header/recordDefArray.h");
352 Translate(headerFile, "common", "header/endWriteonly.h");
354 /*-----------------------------------------------------------------
355 01. Generate the driver's extraneous variables structure.
356 -----------------------------------------------------------------*/
357 TranslationSetFreeFormat("user-defined extraneous registers");
358 TranslationSetDummyString("");
359 Translate(headerFile, "common", "header/structHead.h");
360 for (i = 0; i < numRegisters; i++) {
361 if (registers[i].rar == AMEX) { /* is it is extraneous? */
362 TranslationSetRegDepth(registers[i].depth);
363 TranslationSetRegType(registers[i].size);
364 TranslationSetRegName(registers[i].name);
365 if (registers[i].depth <= 1) { /* one register */
366 TranslationSetFreeFormat("user-def reg");
367 Translate(headerFile, "common",
368 "header/recordDefScalar.h");
369 } else { /* massive */
370 TranslationSetFreeFormat("user-def regs");
371 Translate(headerFile, "common",
372 "header/recordDefArray.h");
376 Translate(headerFile, "common", "header/endExtraneous.h");
378 /*------------------------------------------------------
379 02. Generate device memory map topology structures.
380 ------------------------------------------------------*/
381 endOfBlock = TRUE;
382 for (i = 0; i < numRegisters; i++) {
383 if (registers[i].rar != AMEX) {
384 /* exclude extraneous registers */
385 if (endOfBlock) {
386 /* If we just ended a block then we must be
387 starting a new one */
388 TranslationSetFreeFormat
389 ("Blk[#%d]@addr[#%d] Offs 0x%x."
390 " Sz %d bytes. %d reg(s). %d gap(s)",
391 registers[i].blockP->blockID,
392 registers[i].blockP->blkBaseAddr,
393 registers[i].blockP->offset,
394 (type == SIM_FT) ?
395 registers[i].blockP->blksz_sim :
396 registers[i].blockP->blksz_drvr,
397 registers[i].blockP->reg_am,
398 calc_block_gap_amount(&registers[i]));
399 TranslationSetDummyString("volatile");
400 Translate(headerFile, "common",
401 "header/structHead.h");
405 If this is the first register in a block, check that
406 it's offset is 0. If not then insert some dummy
407 records into the structure to take up the spare
408 space.
411 if (type == DRIVER_FT) {
412 /* we need to set gaps only for real driver */
413 if (endOfBlock) {
414 /* If we just ended a block then we
415 must be starting a new one */
416 prevFreeAddr = 0;
417 theGap = registers[i].offset;
418 } else {
419 prevFreeAddr =
420 registers[i - 1].offset +
421 ((registers[i - 1].depth) ?
422 registers[i - 1].depth :
423 1) * registers[i - 1].regSize;
424 theGap =
425 registers[i].offset - prevFreeAddr;
428 if (theGap > 0) {
429 TranslationSetFancyNum(i);
430 TranslationSetRegDepth(theGap);
431 TranslationSetFreeFormat("0x%x - 0x%x",
432 prevFreeAddr,
433 registers[i].
434 offset);
435 Translate(headerFile, "common",
436 "header/dummyRecord.h");
440 /* Produce a record in the structure for our register */
441 TranslationSetRegType(registers[i].size);
442 TranslationSetRegName(registers[i].name);
443 TranslationSetRegDepth(registers[i].depth);
444 if (registers[i].depth <= 1) { /* one register */
445 TranslationSetFreeFormat("0x%x",
446 registers[i].offset);
447 Translate(headerFile, "common",
448 "header/recordDefScalar.h");
449 } else { /* massive */
450 /* register offset (i.e. Base Address) */
451 unsigned int regBA = registers[i].offset;
453 /* last valid massive address (i.e. address
454 of the last register in massive) */
455 unsigned int regLA = regBA +
456 (registers[i].depth - 1) *
457 registers[i].regSize;
458 TranslationSetFreeFormat("0x%x - 0x%x", regBA,
459 regLA);
460 Translate(headerFile, "common",
461 "header/recordDefArray.h");
464 /* Determine whether we should terminate this
465 structure */
466 if (i == numRegisters - 1)
467 endOfBlock = TRUE;
468 else if (registers[i].blockP->blockID !=
469 registers[i + 1].blockP->blockID)
470 endOfBlock = TRUE;
471 else
472 endOfBlock = FALSE;
474 if (endOfBlock) {
475 TranslationSetFancyNum(registers[i].blockP->
476 blockID);
477 if (type == DRIVER_FT)
478 Translate(headerFile, "common",
479 "header/endDrvrBlock.h");
480 else
481 Translate(headerFile, "common",
482 "header/endSimBlock.h");
484 } /* end of 'rar != AMEX' */
485 } /* end of for */
489 * @brief Generate @b DEPRECATED @e IoctlAccess library.
491 * @param registers -- register description
492 * @param numRegisters -- register amount
493 * @param blocks -- block description
494 * @param numBlocks -- block amount
496 * This library enables user to use old-style ioctl calls to access the driver.
498 * @return void
500 void BuildIoctlLibrary(RegisterDef_t * registers, int numRegisters,
501 BlockDef_t * blocks, int numBlocks)
503 int cntr;
504 char accessType[8];
505 FILE *libraryFile;
506 FILE *headerFile;
507 char *bus = TranslationGetBus(); /* 'VME' or 'DRM' */
509 TranslationReset();
510 libraryFile = OpenFile(COMMON_FT, LOC_LIB, "IoctlAccess.c");
511 headerFile = OpenFile(COMMON_FT, LOC_INCL, "IoctlAccess.h");
513 Translate(libraryFile, bus, "lib/IoctlAccess/head.c");
514 Translate(libraryFile, "common", "lib/ioctlAccess/enableAccess.c");
516 TranslationSetFreeFormat("%s", DG_INC_DIR);
517 Translate(headerFile, bus, "lib/IoctlAccess/headerHead.h");
518 Translate(headerFile, "common", "lib/ioctlAccess/enableAccess.h");
520 /* Generate the get and set functions for each register and write to
521 the library source file, and generate function prototypes for each
522 get and set function and write to the library's header file. */
523 for (cntr = 0; cntr < numRegisters; cntr++) {
524 TranslationSetRegName(registers[cntr].name);
525 TranslationSetRegType(registers[cntr].size);
526 TranslationSetRegDepth(registers[cntr].depth);
528 if (registers[cntr].depth <= 1)
529 strcpy(accessType, "Scalar");
530 else
531 strcpy(accessType, "Array");
533 switch (registers[cntr].rar) {
534 case AMRD: /* 'r' */
535 TranslationSetIoctlConst("GET",
536 registers[cntr].upperName);
537 Translate(libraryFile, "common",
538 "lib/ioctlAccess/get%s.c", accessType);
539 Translate(headerFile, "common",
540 "lib/ioctlAccess/get%s.h", accessType);
541 break;
542 case AMWR: /* 'w' */
543 TranslationSetIoctlConst("GET_HISTORY",
544 registers[cntr].upperName);
545 Translate(libraryFile, "common",
546 "lib/ioctlAccess/getLastHisWo%s.c",
547 accessType);
548 Translate(headerFile, "common",
549 "lib/ioctlAccess/getLastHisWo%s.h",
550 accessType);
552 TranslationSetIoctlConst("SET",
553 registers[cntr].upperName);
554 Translate(libraryFile, "common",
555 "lib/ioctlAccess/set%s.c", accessType);
556 Translate(headerFile, "common",
557 "lib/ioctlAccess/set%s.h", accessType);
558 break;
559 case (AMWR | AMRD): /* 'rw' */
560 case AMEX: /* 'e' */
561 TranslationSetIoctlConst("GET",
562 registers[cntr].upperName);
563 Translate(libraryFile, "common",
564 "lib/ioctlAccess/get%s.c", accessType);
565 Translate(headerFile, "common",
566 "lib/ioctlAccess/get%s.h", accessType);
568 TranslationSetIoctlConst("SET",
569 registers[cntr].upperName);
570 Translate(libraryFile, "common",
571 "lib/ioctlAccess/set%s.c", accessType);
572 Translate(headerFile, "common",
573 "lib/ioctlAccess/set%s.h", accessType);
574 break;
575 default:
576 FATAL_ERR();
577 break;
580 Translate(headerFile, "common", "lib/ioctlAccess/headerFoot.h");
582 fclose(libraryFile);
583 fclose(headerFile);
587 * @brief Builds test program that user will use to test driver/simulator.
589 * @param registers -- register description
590 * @param numRegisters -- register amount
591 * @param blocks -- block description
592 * @param numBlocks -- block amount
594 * @return void
596 void BuildTestProgram(RegisterDef_t * registers, int numRegisters,
597 BlockDef_t * blocks, int numBlocks)
599 FILE *tstFileC = OpenFile(COMMON_FT, LOC_FCLTY, "Test.c");
600 char *bus = TranslationGetBus(); /* 'VME' or 'DRM' */
601 unsigned int freeEntry = TST_PROG_FIRST_FREE_ENTRY; /* */
602 int count;
603 int i;
605 TranslationReset();
606 /* Generate the needed block size consts and register
607 description strings */
608 BuildTestProgHFile(registers, numRegisters);
609 BuildTestProgConsts(registers, numRegisters, tstFileC);
611 /* Generate the remainder of the head and the start of main */
612 Translate(tstFileC, "common", "testProg/common/testMainBegin.c");
613 Translate(tstFileC, "common", "testProg/testMainMenu.c");
615 /* For each block that's been defined, generate an entry in the
616 program's main menu. */
617 for (count = freeEntry, i = 0; i < numBlocks; i++, count++) {
618 TranslationSetFancyNum(count);
619 TranslationSetPlainNum(blocks[i].blockID);
620 Translate(tstFileC, "common",
621 "testProg/common/mainMenuEntry.c");
624 /* Add the PCI config menu item (in case of DRM usage),
625 and the other common options. */
626 Translate(tstFileC, bus, "testProg/mainMenuFoot.c");
627 Translate(tstFileC, "common", "testProg/mainCaseHead.c");
629 /* Generate the case statements for each of the main menu entries. */
630 for (count = freeEntry, i = 0; i < numBlocks; i++, count++) {
631 TranslationSetFancyNum(blocks[i].blockID);
632 TranslationSetPlainNum(count);
633 Translate(tstFileC, "common", "testProg/common/case.c");
636 TranslationSetPlainNum(count);
637 Translate(tstFileC, bus, "testProg/mainCaseFoot.c");
639 BuildTestProgSubMenus(registers, blocks, numRegisters, tstFileC);
641 fclose(tstFileC);
645 * @brief Generates the makefiles that are used to build the generated
646 * suite of code.
648 * @param none
650 * @return void
652 void BuildMakefiles()
654 FILE *mkfd;
655 char dirPath[MAXPATHLEN] = { 0 };
657 TranslationReset();
659 /* Base Makefile */
660 mkfd = OpenFile(EXACT_FT, LOC_MODSRC, "Makefile.base");
661 Translate(mkfd, "common", "makefiles/Makefile.base");
662 fclose(mkfd);
664 /* Specific Makefile */
665 mkfd = OpenFile(EXACT_FT, LOC_MODSRC, "Makefile.specific");
666 Translate(mkfd, "common", "makefiles/Makefile.specific");
667 fclose(mkfd);
669 /* "Which dirs to compile" Makefile */
670 mkfd = OpenFile(EXACT_FT, LOC_MODSRC, "Makefile");
671 Translate(mkfd, "common", "makefiles/Makefile");
672 fclose(mkfd);
674 /* delivery */
675 mkfd = OpenFile(EXACT_FT, LOC_MODSRC, "deliver.mk");
676 Translate(mkfd, "common", "makefiles/deliver.mk");
677 fclose(mkfd);
679 /* Library Makefile */
680 mkfd = OpenFile(EXACT_FT, LOC_LIB, "Makefile");
681 Translate(mkfd, "common", "makefiles/libModule.mk");
682 fclose(mkfd);
684 /* Driver Makefiles */
685 mkfd = OpenFile(EXACT_FT, LOC_DRVR, "makefiles/drvr-linux.mk");
686 Translate(mkfd, "common", "makefiles/drvr-linux.mk");
687 fclose(mkfd);
689 mkfd = OpenFile(EXACT_FT, LOC_DRVR, "makefiles/drvr-lynx.mk");
690 Translate(mkfd, "common", "makefiles/drvr-lynx.mk");
691 fclose(mkfd);
693 mkfd = OpenFile(EXACT_FT, LOC_DRVR, "makefiles/Kbuild");
694 Translate(mkfd, "common", "makefiles/Kbuild");
695 fclose(mkfd);
697 mkfd = OpenFile(EXACT_FT, LOC_DRVR, "makefiles/drvr-paramount.mk");
698 Translate(mkfd, "common", "makefiles/drvr-paramount.mk");
699 fclose(mkfd);
701 mkfd = OpenFile(EXACT_FT, LOC_DRVR, "Makefile");
702 Translate(mkfd, "common", "makefiles/Makefile.drvr");
703 fclose(mkfd);
705 mkfd = OpenFile(EXACT_FT, LOC_DRVR, "compiledrvr");
706 Translate(mkfd, "common", "makefiles/compiledrvr");
707 fchmod(fileno(mkfd),
708 S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH);
709 fclose(mkfd);
711 /* we need this symlink for Kbuild to work */
712 sprintf(dirPath, "%s%s", GetLocalDrvrDir(), "/Kbuild");
713 symlink("makefiles/Kbuild", dirPath);
715 /* Facility (test program) Makefile */
716 mkfd = OpenFile(EXACT_FT, LOC_FCLTY, "Makefile");
717 TranslationSetFreeFormat("%s", DAL_DIR);
718 Translate(mkfd, "common", "makefiles/test.mk");
719 fclose(mkfd);
721 /* Include Makefile */
722 mkfd = OpenFile(EXACT_FT, LOC_INCL, "Makefile");
723 Translate(mkfd, "common", "makefiles/include.mk");
724 fclose(mkfd);
726 /* Install program entry point Makefile */
727 mkfd = OpenFile(EXACT_FT, LOC_INST, "Makefile");
728 TranslationSetFreeFormat("%s", DAL_DIR);
729 Translate(mkfd, "common", "makefiles/installso.mk");
730 fclose(mkfd);
734 * @brief Create (if it was not done yet) main installation directory, where
735 * newly created drivers are located.
737 * @param mdn -- Module Description
738 * If NULL, current master directory name will be returned.
740 * Will be created only *once*. Creates all general-purpose files that should
741 * present in the master diretory (user-part source copy utility for example).
743 * If directory is created already, than no action perfomed exept of returning
744 * the directory name.
746 * @return Main Installation Directory name
748 char *get_mid(struct mdescr *md)
750 static char *mainDir = NULL; /* container */
751 char *cwd = ""; /* current working directory */
752 rstat ret;
754 if (mainDir) /* master dir was already created */
755 return mainDir;
757 /* master dir is not yet created */
758 mainDir = (char *)calloc((strlen(cwd) + strlen(md->mdn) + 2), sizeof(char));
759 sprintf(mainDir, "%s%s", cwd, md->mdn);
761 ret = MakeSafeDir(mainDir);
762 if (ret == -DRIVER_GEN_BAD)
763 exit(EXIT_FAILURE); /* 1 */
765 /* make symlinks to the general utilities
766 (script for copy user-part src code) */
768 struct stat status;
769 char loc_link[128]; /* local utility symlink */
770 char glob_link[128]; /* global utility symlink */
771 char gen_dir[128];
773 sprintf(loc_link, "%s/%s", mainDir, UTIL_CP_USR_PT_LOC);
774 sprintf(glob_link, "%s/%s", mainDir, UTIL_CP_USR_PT_GLOB);
775 sprintf(gen_dir, "%s/%s", mainDir, GENERAL_DIR);
777 if (lstat(glob_link, &status)) /* global symlink doesn't
778 exist */
779 symlink(GenerateFilename(EXACT_FT, DG_DIR_PATH,
780 "scripts/" UTIL_CP_USR_PT_GLOB, NULL, NULL),
781 glob_link);
783 if (!stat(gen_dir, &status))
784 /* we have 'general' dir locally, so create local
785 symlink */
786 if (lstat(loc_link, &status)) /* local symlink doesn't
787 exist */
788 symlink(GenerateFilename
789 (EXACT_FT, GENERAL_DIR,
790 UTIL_CP_USR_PT_GLOB, NULL, NULL),
791 loc_link);
794 return (mainDir);
798 * @brief Get Module Source code Directory.
800 * @param md -- module description
802 * Creates directory, where Driver/Simulator source code of a currently
803 * processed module will be located. If directory is already created, than no
804 * action perfomed exept of returning the directory name.
806 * @return directory name for driver src code.
808 char *get_msd(struct mdescr *md)
810 static char *sourceDir = NULL; /* container */
811 time_t theTime;
812 struct tm *tmPtr;
813 char timeStr[MAX_STR];
814 char *tFmt;
816 if (sourceDir) /* driver source dir is already created */
817 return sourceDir;
819 /* Driver directory is not created yet */
820 time(&theTime);
821 tmPtr = localtime(&theTime);
823 /* obfuscate 'gcc' to bypass warnings about format string */
824 tFmt = "%d%b%G.%Hh%Mm%Ss";
826 strftime(timeStr, sizeof(timeStr), tFmt, tmPtr);
828 sourceDir = (char *)calloc(MAXPATHLEN, sizeof(char));
829 if (md->isgit)
830 snprintf(sourceDir, MAXPATHLEN, "%s/%s",
831 get_mid(NULL), TranslationGetModName());
832 else
833 snprintf(sourceDir, MAXPATHLEN, "%s/%s.%s",
834 get_mid(NULL), TranslationGetModName(), timeStr);
836 if (MakeSafeDir(sourceDir) == -DRIVER_GEN_BAD)
837 exit(EXIT_FAILURE); /* 1 */
839 return sourceDir;
843 * @brief Build the driver's Ioctl routine.
845 * @param registers -- register description
846 * @param numRegisters -- register amount
847 * @param driverFile -- open file descriptor
849 void BuildDrvrSimIoctl(RegisterDef_t * registers, int numRegisters,
850 FILE * driverFile)
852 int cntr;
854 TranslationReset();
855 Translate(driverFile, "common", "driver/ioctl/head.c");
857 /* first, build 'service' registers ioctl */
858 TranslationSetBaseAddr("");
859 for (cntr = 0; cntr < GetSrvRegNum(); cntr++) {
860 TranslationSetRegName(srv_ioctl[cntr].name);
861 switch (srv_ioctl[cntr].rar) {
862 case AMRD: /* 'r' */
863 TranslationSetIoctlConst("GET", srv_ioctl[cntr].name);
864 TranslationSetRegType("get");
865 Translate(driverFile, "common",
866 "driver/ioctl/getSetReg.c");
867 break;
868 case AMWR: /* 'w' */
869 TranslationSetIoctlConst("SET", srv_ioctl[cntr].name);
870 TranslationSetRegType("set");
871 Translate(driverFile, "common",
872 "driver/ioctl/getSetReg.c");
873 break;
874 case (AMWR | AMRD): /* 'rw' */
875 TranslationSetIoctlConst("GET", srv_ioctl[cntr].name);
876 TranslationSetRegType("get");
877 Translate(driverFile, "common",
878 "driver/ioctl/getSetReg.c");
880 TranslationSetIoctlConst("SET", srv_ioctl[cntr].name);
881 TranslationSetRegType("set");
882 Translate(driverFile, "common",
883 "driver/ioctl/getSetReg.c");
884 break;
885 default:
886 TranslationSetIoctlConst("", srv_ioctl[cntr].name);
887 TranslationSetRegType("srv_func");
888 Translate(driverFile, "common",
889 "driver/ioctl/getSetReg.c");
890 break;
894 /* now build-up r/w operations for the normal registers */
895 for (cntr = 0; cntr < numRegisters; cntr++) {
896 TranslationSetRegName(registers[cntr].name);
897 switch (registers[cntr].rar) {
898 case AMRD: /* 'r' read-only reg */
899 TranslationSetIoctlConst("GET",
900 registers[cntr].upperName);
901 TranslationSetBaseAddr("");
902 TranslationSetRegType("get");
903 Translate(driverFile, "common",
904 "driver/ioctl/getSetReg.c");
905 break;
906 case AMWR: /* 'w' write-only reg */
907 TranslationSetIoctlConst("GET_HISTORY",
908 registers[cntr].upperName);
909 TranslationSetBaseAddr("wo_");
910 TranslationSetRegType("get");
911 Translate(driverFile, "common",
912 "driver/ioctl/getSetReg.c");
914 TranslationSetIoctlConst("SET",
915 registers[cntr].upperName);
916 TranslationSetBaseAddr("");
917 TranslationSetRegType("set");
918 Translate(driverFile, "common",
919 "driver/ioctl/getSetReg.c");
920 break;
921 case (AMWR | AMRD): /* 'rw' read/write reg */
922 TranslationSetIoctlConst("GET",
923 registers[cntr].upperName);
924 TranslationSetBaseAddr("");
925 TranslationSetRegType("get");
926 Translate(driverFile, "common",
927 "driver/ioctl/getSetReg.c");
929 TranslationSetIoctlConst("SET",
930 registers[cntr].upperName);
931 TranslationSetBaseAddr("");
932 TranslationSetRegType("set");
933 Translate(driverFile, "common",
934 "driver/ioctl/getSetReg.c");
935 break;
936 case AMEX: /* 'e' extraneous (i.e. w/r) reg */
937 TranslationSetIoctlConst("GET",
938 registers[cntr].upperName);
939 TranslationSetBaseAddr("ex_");
940 TranslationSetRegType("get");
941 Translate(driverFile, "common",
942 "driver/ioctl/getSetReg.c");
944 TranslationSetIoctlConst("SET",
945 registers[cntr].upperName);
946 TranslationSetBaseAddr("ex_");
947 TranslationSetRegType("set");
948 Translate(driverFile, "common",
949 "driver/ioctl/getSetReg.c");
950 break;
951 default:
952 FATAL_ERR();
953 break;
956 Translate(driverFile, "common", "driver/ioctl/foot.c");
960 * @brief Generate the get and set (or r/w) functions
962 * @param registers -- register description
963 * @param numRegisters -- register amount
964 * @param vmeInfo -- @e vme description
966 * Header file with their declaration is also created. This functions are used
967 * by the driver ioctl routine to access hardware registers. @b CH in the name
968 * stands for @e c source file and @e h header file.
970 * @return void
972 void BuildGetSetRegCH(RegisterDef_t * registers, int numRegisters,
973 VmeInfo_t * vmeInfo)
975 FILE *c_fd = OpenFile(COMMON_FT, LOC_DRVR, "GetSetReg.inc.c");
976 FILE *h_fd = OpenFile(COMMON_FT, LOC_INCL, "GetSetReg.h");
977 char *bus = TranslationGetBus(); /* 'VME' or 'DRM' */
978 char accessType[MIN_STR], *strDps, singularity[16], *rsz;
979 int cntr;
980 long dps; /* address space data port size */
981 char singular_comment_str[256];
982 char *cmt =
983 " These functions are used to deliver register values directly"
984 " to the user\n space.\n\n"
985 " API is the following:\n"
986 " 1 param -- statics table\n\n"
987 " 2 param -- ioctl argument in predefined format:\n"
988 " Massive of 3 elements, each is 4 bytes long.\n"
989 " [0] - user-space address\n"
990 " [1] - number of elements to r/w\n"
991 " [2] - element index, starting from zero\n\n"
992 " In case of service registers -- ioctl arguments"
993 " can vary.\n"
994 " Their amount depends on specific ioctl number.\n"
995 " See service routines (those are with __SRV__"
996 " subword)\n"
997 " for more details on parameter amount.\n\n"
998 " For example, if this is a repetitive r/w"
999 " request\n"
1000 " (ioctl number is SRV__REP_REG_RW) then we should"
1001 " have 4 arguments,\n"
1002 " that are packed as follows:\n\n"
1003 " [0] -- ioctl number\n"
1004 " [1] -- user-space address\n"
1005 " [2] -- number of elements to r/w\n"
1006 " [3] -- element index, starting from zero\n\n"
1007 " 3 param -- check r/w bounds (1 - yes, 0 - no)\n"
1008 " valid only in case of Lynx\n"
1009 " 4 param -- repeatedly read register (1 - yes, 0 - no)\n\n\n"
1010 " Bear in mind, that r/w operation results goes diretly to"
1011 " the user space.\n"
1012 " If you want to operate on the HW registers inside the"
1013 " driver -- use\n"
1014 " low-level port operation functions from"
1015 " port_ops_[linux/lynx].h like:\n"
1016 " __inb -- read a byte from a port\n"
1017 " __inw -- read a word from a port\n"
1018 " __in -- lread a long from a port\n"
1019 " __outb -- write a byte to a port\n"
1020 " __outw -- write a word to a port\n"
1021 " __outl -- write a long to a port\n"
1022 " __rep_inb -- read multiple bytes from a port into a"
1023 " buffer\n"
1024 " __rep_inw -- read multiple words from a port into a"
1025 " buffer\n"
1026 " __rep_inl -- read multiple longs from a port into a"
1027 " buffer\n"
1028 " __rep_outb -- write multiple bytes to a port from a buffer\n"
1029 " __rep_outw -- write multiple words to a port from a buffer\n"
1030 " __rep_outl -- write multiple longs to a port from a"
1031 " buffer\n\n"
1032 " These functions are used to r/w HW registers inside the"
1033 " driver.\n"
1034 " Never access registers directly. Use this function to do"
1035 " this.";
1037 Translate(c_fd, "common", "driver/getSetReg/funcDefs.c");
1039 /* ----------> first handle service registers <------------------- */
1041 /* C file */
1042 TranslationSetIntNum(sizeof(time_t));
1043 TranslationSetRegType(srv_ioctl[3].type); /* size of DAL_CONSISTENT
1044 register */
1045 Translate(c_fd, bus, "driver/getSetReg/srvRegOps.c");
1047 /* header file starts */
1048 TranslationSetFancyString("GET_SET_REG");
1049 Translate(h_fd, "common", "header/headerStartEnd/hsModNmStr.h");
1050 TranslationSetComment(cmt);
1052 Translate(h_fd, "common", "dummyTemplates/comment-multiline");
1054 /* srv regs functions declaration */
1055 Translate(h_fd, "common", "dummyTemplates/1NewLine");
1056 TranslationSetComment("Service register operations");
1057 Translate(h_fd, "common", "dummyTemplates/comment");
1058 TranslationSetBaseAddr("");
1059 for (cntr = 0; cntr < GetSrvRegNum(); cntr++) {
1060 TranslationSetRegName(srv_ioctl[cntr].name);
1061 if (srv_ioctl[cntr].rar & AMRD) { /* get register function */
1062 TranslationSetRegType("get");
1063 Translate(h_fd, "common",
1064 "driver/getSetReg/declGetSet.h");
1066 if (srv_ioctl[cntr].rar & AMWR) { /* set register function */
1067 TranslationSetRegType("set");
1068 Translate(h_fd, "common",
1069 "driver/getSetReg/declGetSet.h");
1073 /* ---------------> now handle all module registers <------------- */
1074 for (cntr = 0; cntr < numRegisters; cntr++) {
1075 TranslationSetRegName(registers[cntr].name);
1076 TranslationSetRegType(registers[cntr].size);
1077 TranslationSetRegComm(registers[cntr].comment);
1078 TranslationSetRegLoop(registers[cntr].timeLoop);
1079 TranslationSetFreeFormat("block%02d",
1080 registers[cntr].blockP->blockID);
1082 switch (registers[cntr].regSize) {
1083 case 1:
1084 rsz = "b";
1085 TranslationSetRegSize(8);
1086 break;
1087 case 2:
1088 rsz = "w";
1089 TranslationSetRegSize(16);
1090 break;
1091 case 4:
1092 rsz = "l";
1093 TranslationSetRegSize(32);
1094 break;
1095 case 8:
1096 rsz = "ll";
1097 TranslationSetRegSize(64);
1098 break;
1099 default:
1100 FATAL_ERR();
1101 break;
1104 TranslationSetChar(*rsz); /* set read/write port
1105 operation suffix */
1107 /* manage dataport size */
1108 if (registers[cntr].blockP->blkBaseAddr == 1)
1109 dps = vmeInfo->addr1.dpSize;
1110 else
1111 dps = vmeInfo->addr2.dpSize;
1113 /* set max allowed r/w size */
1114 switch (dps) {
1115 case 8:
1116 strDps = "char";
1117 rsz = "b";
1118 break;
1119 case 16:
1120 strDps = "short";
1121 rsz = "w";
1122 break;
1123 case 32:
1124 strDps = "long";
1125 rsz = "l";
1126 break;
1127 case 64:
1128 strDps = "long long";
1129 rsz = "ll";
1130 break;
1131 default:
1132 fprintf(stderr, "%s Data Port Size is NOT provided in"
1133 " the DB.\n", ERROR_MSG);
1134 FATAL_ERR();
1135 break;
1138 /* singularity comment string format */
1139 #define COMMENT_SINGULAR \
1140 " *\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 *"
1142 /* if register size is bigger than Data Port Size, then
1143 register is considered to be singular and will be
1144 read/written in parts. In this case we should adjust
1145 register type and r/w port suffix to the max allowed
1146 (i.e. the data port size) */
1147 if (dps / 8 /*convert to bytes */ < registers[cntr].regSize) {
1148 /* reg type (char, short, long) */
1149 TranslationSetRegType(strDps);
1150 /* read/write port operation suffix */
1151 TranslationSetChar(*rsz);
1154 /* if register size is bigger than MAX data width */
1155 if (registers[cntr].rar & AMEX) {
1156 /* ignore fake external registers */
1157 strcpy(singularity, "Extraneous");
1158 TranslationSetComment(" *");
1159 } else {
1160 if (registers[cntr].regSize * 8 > dps) {
1161 /* build-up singularitiy comment string
1162 for the user */
1163 snprintf(singular_comment_str,
1164 sizeof(singular_comment_str),
1165 COMMENT_SINGULAR,
1166 registers[cntr].regSize,
1167 registers[cntr].blockP->blkBaseAddr,
1168 (int)dps / 8);
1169 strcpy(singularity, "Singular");
1170 TranslationSetComment(singular_comment_str);
1171 } else {
1172 strcpy(singularity, "Normal");
1173 TranslationSetComment(" *");
1177 TranslationSetFancyString(singularity);
1179 /* if this register is a scalar, fifo or an array */
1180 if (registers[cntr].depth <= 1)
1181 strcpy(accessType, "scalar");
1182 else
1183 strcpy(accessType, "array");
1185 /* generate get/set methods depending on the register's
1186 description */
1187 switch (registers[cntr].rar) {
1188 case AMWR: /* 'w' write-only reg */
1189 /* c file */
1190 Translate(c_fd, "common",
1191 "driver/getSetReg/func_comment.c");
1192 Translate(c_fd, "common", "driver/getSetReg/wo_%s.c",
1193 accessType);
1195 /* header file */
1196 Translate(h_fd, "common", "dummyTemplates/1NewLine");
1197 TranslationSetComment(registers[cntr].comment);
1198 Translate(h_fd, "common", "dummyTemplates/comment");
1199 TranslationSetBaseAddr("wo_");
1200 TranslationSetRegType("get");
1201 Translate(h_fd, "common",
1202 "driver/getSetReg/declGetSet.h");
1203 TranslationSetBaseAddr("");
1204 TranslationSetRegType("set");
1205 Translate(h_fd, "common",
1206 "driver/getSetReg/declGetSet.h");
1207 break;
1208 case AMRD: /* 'r' read-only reg */
1209 /* c file */
1210 Translate(c_fd, "common",
1211 "driver/getSetReg/func_comment.c");
1212 Translate(c_fd, "common", "driver/getSetReg/ro_%s.c",
1213 accessType);
1215 /* header file */
1216 Translate(h_fd, "common", "dummyTemplates/1NewLine");
1217 TranslationSetComment(registers[cntr].comment);
1218 Translate(h_fd, "common", "dummyTemplates/comment");
1219 TranslationSetBaseAddr("");
1220 TranslationSetRegType("get");
1221 Translate(h_fd, "common",
1222 "driver/getSetReg/declGetSet.h");
1223 break;
1224 case (AMWR | AMRD): /* 'wr' read/write reg */
1225 /* c file */
1226 Translate(c_fd, "common",
1227 "driver/getSetReg/func_comment.c");
1228 Translate(c_fd, "common", "driver/getSetReg/rw_%s.c",
1229 accessType);
1231 /* header file */
1232 Translate(h_fd, "common", "dummyTemplates/1NewLine");
1233 TranslationSetComment(registers[cntr].comment);
1234 Translate(h_fd, "common", "dummyTemplates/comment");
1235 TranslationSetBaseAddr("");
1236 TranslationSetRegType("get");
1237 Translate(h_fd, "common",
1238 "driver/getSetReg/declGetSet.h");
1239 TranslationSetRegType("set");
1240 Translate(h_fd, "common",
1241 "driver/getSetReg/declGetSet.h");
1242 break;
1243 case AMEX: /* 'e' extraneous reg. They are always r/w */
1244 /* c file */
1245 Translate(c_fd, "common",
1246 "driver/getSetReg/func_comment.c");
1247 Translate(c_fd, "common", "driver/getSetReg/ex_%s.c",
1248 accessType);
1250 /* header file */
1251 Translate(h_fd, "common", "dummyTemplates/1NewLine");
1252 TranslationSetComment(registers[cntr].comment);
1253 Translate(h_fd, "common", "dummyTemplates/comment");
1254 TranslationSetBaseAddr("ex_");
1255 TranslationSetRegType("get");
1256 Translate(h_fd, "common",
1257 "driver/getSetReg/declGetSet.h");
1258 TranslationSetRegType("set");
1259 Translate(h_fd, "common",
1260 "driver/getSetReg/declGetSet.h");
1261 break;
1262 default:
1263 break;
1265 } /* end of 'for(cntr = 0; cntr < numRegisters; cntr++)' */
1267 /* header ends */
1268 TranslationSetFancyString("GET_SET_REG");
1269 Translate(h_fd, "common", "header/headerStartEnd/heModNmStr.h");
1271 fclose(c_fd);
1272 fclose(h_fd);
1276 * @brief Generates src code and header files that are common to all
1277 * Module drivers.
1279 * @param none
1281 * It includes header files, libraries and installation/deinstallation
1282 * programs.
1284 * @return void
1286 void BuildGeneralCode()
1288 char *bus = TranslationGetBus(); /* 'VME' or 'DRM' */
1290 printf("Building general header files for '%s' modules.\n", bus);
1291 BuildGeneralHeaderFiles();
1293 printf("Building general libraries for '%s' modules.\n", bus);
1294 BuildGeneralLibraries();
1296 printf("Building general install program for '%s' modules.\n", bus);
1297 BuildGeneralInstallProgram();
1299 printf("Building general Makefiles for '%s' modules.\n", bus);
1300 BuildGeneralMakefiles();
1302 /* instantiate scripts */
1303 printf("Instantiate supplementary scripts.\n");
1304 BuildGeneralScripts();
1308 * @brief Generates files and directories, intended for user intervention.
1310 * @param none
1312 * These are so-called <E>user entry points</E>. This is a user part of the
1313 * driver. User is allowed to modify this code if he wants to implement his
1314 * own code. There are three entry points. They are: in the driver/simulator,
1315 * in the test program and also a library framework for driver accessing in
1316 * case if user wants to define his own library code.
1318 * @return void
1320 void BuildUserPartDrvrCode()
1322 FILE *file;
1323 char *system;
1325 system = TranslationGetModName();
1327 /* 0x0 build user entry points and header files for the driver */
1328 /* c-file for real driver */
1329 //printf("Building %s driver's user-defined entry poins.\n", system);
1330 TranslationSetDriverType("DRVR");
1331 TranslationSetFancyString("Drvr");
1332 TranslationSetChar('D');
1333 file = OpenFile(DRIVER_FT, LOC_DRVR, "%s/%s.c", LOCAL_USER_DIR,
1334 USER_SUBWORD_LEXEME);
1335 Translate(file, "common", "driver/userPart/uepHead.c");
1336 Translate(file, "common", "driver/isr.c"); /* generate empty ISR */
1337 Translate(file, "common", "driver/userPart/uepFoot.c");
1338 fclose(file);
1340 /* h-file for real driver */
1341 file = OpenFile(DRIVER_FT, LOC_INCL, "%s/%s.h", LOCAL_USER_DIR,
1342 USER_SUBWORD_LEXEME);
1343 Translate(file, "common", "driver/userPart/uep.h");
1344 fclose(file);
1346 /* c-file for driver simulator */
1347 //printf("Building %s simulator's user-defined entry poins.\n", system);
1348 TranslationSetDriverType("SIM");
1349 TranslationSetFancyString("Sim");
1350 TranslationSetChar('S');
1351 file =OpenFile(SIM_FT, LOC_DRVR, "%s/%s.c", LOCAL_USER_DIR,
1352 USER_SUBWORD_LEXEME);
1353 Translate(file, "common", "driver/userPart/uepHead.c");
1354 Translate(file, "common", "driver/isr.c"); /* generate empty ISR */
1355 Translate(file, "common", "driver/userPart/uepFoot.c");
1356 fclose(file);
1358 /* h-file for driver simulator */
1359 file = OpenFile(SIM_FT, LOC_INCL, "%s/%s.h", LOCAL_USER_DIR,
1360 USER_SUBWORD_LEXEME);
1361 Translate(file, "common", "driver/userPart/uep.h");
1362 fclose(file);
1364 /* add 'readme' file */
1365 file = OpenFile(EXACT_FT, LOC_DRVR, "%s/README.1ST", LOCAL_USER_DIR);
1366 Translate(file, "common", "driver/userPart/warnTemplate.txt");
1367 fclose(file);
1369 /* Driver/Simulator version files */
1370 BuildVersionFiles(DRIVER_FT | SIM_FT);
1372 /* 0x1 now build user entry points in the test programm */
1373 //printf("Building %s files for user-defined test program.\n", system);
1374 file = OpenFile(COMMON_FT, LOC_FCLTY, "%s/%sTest.c", LOCAL_USER_DIR,
1375 USER_SUBWORD_LEXEME);
1376 Translate(file, "common", "testProg/common/userTest.c");
1377 fclose(file);
1379 file = OpenFile(COMMON_FT, LOC_FCLTY, "%s/%sTest.h", LOCAL_USER_DIR,
1380 USER_SUBWORD_LEXEME);
1381 Translate(file, "common", "testProg/common/userTest.h");
1382 fclose(file);
1384 /* 0x2 now build user-defined library framework */
1385 //printf("Building %s files for user-defined access library.\n", system);
1386 file = OpenFile(COMMON_FT, LOC_LIB, "%s/%sAccess.c", LOCAL_USER_DIR,
1387 USER_SUBWORD_LEXEME);
1388 Translate(file, "common", "lib/usrAccess/userDefinedAccess.c");
1389 fclose(file);
1391 file = OpenFile(COMMON_FT, LOC_INCL, "%s/%sAccess.h", LOCAL_USER_DIR,
1392 USER_SUBWORD_LEXEME);
1393 Translate(file, "common", "lib/usrAccess/userDefinedAccess.h");
1394 fclose(file);
1396 /* 0x3 Install program entry point */
1397 file = OpenFile(EXACT_FT, LOC_INST, "%s/install-so.c", LOCAL_USER_DIR);
1398 Translate(file, "common", "install/usr-install-so.c");
1399 fclose(file);
1403 * @brief Generates filename based on directory name, filename itself and file
1404 * extension.
1406 * @param type -- Driver, Simulator, common or exact
1407 * @param root -- full directory path
1408 * @param name -- filename
1409 * @param ext -- file extension (i.e. '.h' '.c' etc.)
1410 * @param ret -- where to put the results (if not NULL)
1412 * It also takes in account if it is a driver or driver simulator.\n
1413 * For example if @e type is @b SIM_FT, @b root is @b $HOME/tmp, @e name is
1414 * @b Myname and @e ext is @b .h, than generated filename will be
1415 * @b "$HOME/tmp/<sys_lower>MynameSim.h".\n
1416 * If @e type is @b EXACT_FT than it just generates file with name @b name
1417 * without taking in account if this is a drvr or sim.
1419 * @return Generated filename.
1421 char *GenerateFilename(FILETYPE type, char *root, char *name, char *ext,
1422 char *ret)
1424 static char fn[MAXPATHLEN];
1426 if (type == DRIVER_FT) /* driver */
1427 snprintf(fn, MAXPATHLEN, "%s/%s%sDrvr%s", root,
1428 TranslationGetSysLower(), name, ext);
1429 else if (type == SIM_FT) /* driver simulator */
1430 snprintf(fn, MAXPATHLEN, "%s/%s%sSim%s", root,
1431 TranslationGetSysLower(), name, ext);
1432 else if (type == COMMON_FT) /* common for driver and simulator */
1433 snprintf(fn, MAXPATHLEN, "%s/%s%s%s", root,
1434 TranslationGetSysLower(), name, ext);
1435 else /* file with exact given name
1436 (i.e. type == EXACT_FT) */
1437 snprintf(fn, MAXPATHLEN, "%s/%s", root, name);
1439 #ifdef _VERBOSE_
1440 printf("%s(): Generated filename is-> %s\n", __FUNCTION__, fn);
1441 #endif
1443 if (ret) {
1444 strcpy(ret, fn);
1445 return ret;
1446 } else {
1447 return fn;
1452 * @brief Create version files for real and simulator driver.
1454 * @param ft -- what to build
1456 * @return void
1458 static void BuildVersionFiles(FILETYPE ft)
1460 FILE *file;
1462 if (ft & DRIVER_FT) {
1463 TranslationSetDriverType("DRVR");
1464 TranslationSetFancyString("Driver");
1465 file = OpenFile(DRIVER_FT, LOC_INCL, "%s/%s.h", LOCAL_USER_DIR,
1466 "Version");
1467 Translate(file, "common", "driver/userPart/uepVers.h");
1468 fclose(file);
1471 if (ft & SIM_FT) {
1472 TranslationSetDriverType("SIM");
1473 TranslationSetFancyString("Simulator");
1474 file = OpenFile(SIM_FT, LOC_INCL, "%s/%s.h", LOCAL_USER_DIR,
1475 "Version");
1476 Translate(file, "common", "driver/userPart/uepVers.h");
1477 fclose(file);
1482 * @brief Returns directory name for shared source code of VME/PCI buses.
1484 * @param none
1486 * @return Shared source code directory name (GENERAL_DIR).
1488 static char *GetGeneralSrcDir()
1490 static char *shDir = NULL;
1491 char *mid; /* master install dir */
1493 if (shDir) /* directory is already created, so return */
1494 return (shDir);
1496 mid = get_mid(NULL);
1497 shDir = (char *)calloc((strlen(mid) + strlen(GENERAL_DIR) + 2),
1498 sizeof(char));
1499 sprintf(shDir, "%s/%s", mid, GENERAL_DIR);
1501 if (MakeSafeDir(shDir) == -DRIVER_GEN_BAD)
1502 exit(EXIT_FAILURE); /* 1 */
1504 return shDir;
1508 * @brief local driver diectory name container.
1510 * @param none
1512 * @return local driver diectory name (LOCAL_DRVR_DIR).
1514 static char *GetLocalDrvrDir()
1516 static char *drvrDir = NULL;
1517 char *cmd; /* current module directory */
1519 if (drvrDir) /* directory is already created, so return */
1520 return (drvrDir);
1522 /* directory is not created yet. So DO it. */
1523 cmd = get_msd(NULL);
1524 drvrDir = (char *)calloc((strlen(cmd) + strlen(LOCAL_DRVR_DIR) + 2),
1525 sizeof(char));
1526 sprintf(drvrDir, "%s/%s", cmd, LOCAL_DRVR_DIR);
1528 if (MakeSafeDir(drvrDir) == -DRIVER_GEN_BAD)
1529 exit(EXIT_FAILURE); /* 1 */
1531 return drvrDir;
1535 * @brief local facility directory name container.
1537 * @param none
1539 * @return local facility directory name (LOCAL_FCLTY_DIR).
1541 static char *GetLocalFcltyDir()
1543 static char *fcltyDir = NULL;
1544 char *cmd; /* current module directory */
1546 if (fcltyDir) /* directory is already created, so return */
1547 return (fcltyDir);
1549 /* directory is not created yet. So DO it. */
1550 cmd = get_msd(NULL);
1551 fcltyDir = (char *)calloc((strlen(cmd) + strlen(LOCAL_FCLTY_DIR) + 2),
1552 sizeof(char));
1553 sprintf(fcltyDir, "%s/%s", cmd, LOCAL_FCLTY_DIR);
1555 if (MakeSafeDir(fcltyDir) == -DRIVER_GEN_BAD)
1556 exit(EXIT_FAILURE); /* 1 */
1558 return fcltyDir;
1562 * @brief local include directory name container.
1564 * @param none
1566 * @return local include directory name (LOCAL_INCL_DIR).
1568 static char *GetLocalInclDir()
1570 static char *inclDir = NULL;
1571 char *cmd; /* current module directory */
1573 if (inclDir) /* directory is already created, so return */
1574 return (inclDir);
1576 /* directory is not created yet. So DO it. */
1577 cmd = get_msd(NULL);
1578 inclDir = (char *)calloc((strlen(cmd) + strlen(LOCAL_INCL_DIR) + 2),
1579 sizeof(char));
1580 sprintf(inclDir, "%s/%s", cmd, LOCAL_INCL_DIR);
1582 if (MakeSafeDir(inclDir) == -DRIVER_GEN_BAD)
1583 exit(EXIT_FAILURE); /* 1 */
1585 return (inclDir);
1589 * @brief local library directory name container.
1591 * @param none
1593 * @return local library directory name (LOCAL_LIB_DIR).
1595 static char *GetLocalLibDir()
1597 static char *libDir = NULL;
1598 char *cmd; /* current module directory */
1600 if (libDir) /* directory is already created, so return */
1601 return (libDir);
1603 /* directory is not created yet. So DO it. */
1604 cmd = get_msd(NULL);
1605 libDir = (char *)calloc((strlen(cmd) + strlen(LOCAL_LIB_DIR) + 2),
1606 sizeof(char));
1607 sprintf(libDir, "%s/%s", cmd, LOCAL_LIB_DIR);
1609 if (MakeSafeDir(libDir) == -DRIVER_GEN_BAD)
1610 exit(EXIT_FAILURE); /* 1 */
1612 return libDir;
1616 * @brief installation entry point directory name container.
1618 * @param none
1620 * @return installation directory name (LOCAL_INST_DIR).
1622 static char *GetLocalInstDir()
1624 static char *instDir = NULL;
1625 char *cmd; /* current module directory */
1627 if (instDir) /* directory is already created, so return */
1628 return instDir;
1630 /* directory is not created yet. So DO it. */
1631 cmd = get_msd(NULL);
1632 instDir = (char *)calloc((strlen(cmd) + strlen(LOCAL_INST_DIR) + 2),
1633 sizeof(char));
1634 sprintf(instDir, "%s/%s", cmd, LOCAL_INST_DIR);
1636 if (MakeSafeDir(instDir) == -DRIVER_GEN_BAD)
1637 exit(EXIT_FAILURE); /* 1 */
1639 return instDir;
1643 * @brief Creates directory named @e dirName
1645 * @param dirName -- directory name
1647 * @return -DRIVER_GEN_BAD - in case of error.
1648 * @return DRIVER_GEN_OK - if directory is created.
1649 * @return DRIVER_GEN_EXIST - if directory already exist.
1651 rstat MakeSafeDir(char *dirName)
1653 struct stat status;
1654 rstat ret;
1656 if (!dirName)
1657 return DRIVER_GEN_BAD;
1659 if (stat(dirName, &status)) { /* directory doesn't exist - so create */
1660 umask(0002); /* set tmp mask for dir creation */
1661 if (mkdir(dirName, 0777)) {
1662 ERR_POS("mkdir");
1663 return DRIVER_GEN_BAD;
1665 ret = DRIVER_GEN_OK;
1666 } else /* directory already exist */
1667 ret = DRIVER_GEN_EXIST;
1669 #ifdef _VERBOSE_
1670 printf("%s() Created directory name is: %s\n", __func__, dirName);
1671 #endif
1673 return ret;
1677 * @brief
1679 * @param registers -- register description
1680 * @param numRegisters -- register amount
1682 * @return void
1684 static void BuildTestProgHFile(RegisterDef_t * registers, int numRegisters)
1686 FILE *tstFileH;
1687 int endOfBlock = FALSE;
1688 int i, count = 0, blockcntr = 0, exNum = 0, woNum = 0;
1690 TranslationReset();
1691 tstFileH = OpenFile(COMMON_FT, LOC_FCLTY, "Test.h");
1693 /* Generate the first portion of the test program */
1694 TranslationSetFreeFormat("%s", DG_INC_DIR);
1695 Translate(tstFileH, "common", "testProg/common/headerHead.h");
1697 /* Generate the '*NUM_REGISTERS' constants, there
1698 should be one for each block that has been defined. */
1699 count = 0;
1700 for (i = 0; i < numRegisters; i++) {
1701 count++;
1702 if (i == numRegisters - 1)
1703 endOfBlock = TRUE;
1704 else if (registers[i].blockP->blockID !=
1705 registers[i + 1].blockP->blockID)
1706 endOfBlock = TRUE;
1707 else
1708 endOfBlock = FALSE;
1710 if (endOfBlock) {
1711 blockcntr++; /* block counter */
1712 TranslationSetFancyNum(registers[i].blockP->blockID);
1713 TranslationSetPlainNum(count);
1714 Translate(tstFileH, "common",
1715 "testProg/common/numReg.h");
1716 count = 0;
1718 if (registers[i].rar == AMEX)
1719 exNum++;
1720 if (registers[i].rar == AMWR)
1721 woNum++;
1724 /* Generate tentative function decls. to suppess any
1725 possible warnings */
1726 TranslationSetPlainNum(exNum);
1727 TranslationSetRegDepth(GetSrvRegNum());
1728 TranslationSetPrecision(woNum);
1729 Translate(tstFileH, "common", "testProg/common/tentativeDecl.h");
1730 Translate(tstFileH, "common", "testProg/serviceMenuHead.h");
1731 Translate(tstFileH, "common", "testProg/common/extraneousMenuHead.h");
1732 Translate(tstFileH, "common", "testProg/writeOnlyMenuHead.h");
1733 for (i = 0; i < blockcntr; i++) {
1734 TranslationSetFancyNum(i);
1735 Translate(tstFileH, "common",
1736 "testProg/common/blockMenuHead.h");
1739 Translate(tstFileH, "common", "testProg/common/headerFoot.h");
1740 fclose(tstFileH);
1744 * @brief Generates the first portion of the driver's test program.
1746 * @param registers -- register description
1747 * @param numRegisters -- register amount
1748 * @param testFile -- open file descriptor
1750 * Namely the #includes, #defines and the arrays of strings containing
1751 * register comments.
1753 * @return void
1755 static void BuildTestProgConsts(RegisterDef_t * registers, int numRegisters,
1756 FILE * testFile)
1758 int endOfBlock = FALSE;
1759 int i;
1761 TranslationReset();
1762 Translate(testFile, "common", "testProg/common/testHead.c");
1764 /*------------------------------------------------------------------
1765 00. Generate the register comments string arrays. There should be
1766 an array of string for each defined block
1767 -----------------------------------------------------------------*/
1768 endOfBlock = TRUE;
1769 for (i = 0; i < numRegisters; i++)
1770 if (registers[i].rar != AMEX) {
1771 /* exclude extraneous registers */
1772 TranslationSetFancyNum(registers[i].blockP->blockID);
1773 TranslationSetRegName(registers[i].name);
1774 TranslationSetRegComm(registers[i].comment);
1776 /* If we've just ended a block then this must be
1777 the start of a new one */
1778 if (endOfBlock)
1779 Translate(testFile, "common",
1780 "testProg/common/blockDefHead.c");
1781 Translate(testFile, "common",
1782 "testProg/common/regData.c");
1784 /* Is this the end of a block? */
1785 if (i == numRegisters - 1)
1786 endOfBlock = TRUE;
1787 else if (registers[i].blockP->blockID !=
1788 registers[i + 1].blockP->blockID)
1789 endOfBlock = TRUE;
1790 else
1791 endOfBlock = FALSE;
1793 if (endOfBlock)
1794 Translate(testFile, "common",
1795 "dummyTemplates/endOfBraces");
1798 /*----------------------------------------------------------------
1799 01. Generate the comments string for the extraneous registers.
1800 ----------------------------------------------------------------*/
1801 Translate(testFile, "common", "testProg/common/extraneousDefHead.c");
1802 for (i = 0; i < numRegisters; i++)
1803 if (registers[i].rar == AMEX) { /* is it is extraneous? */
1804 TranslationSetRegName(registers[i].name);
1805 TranslationSetRegComm(registers[i].comment);
1806 Translate(testFile, "common",
1807 "testProg/common/regData.c");
1809 Translate(testFile, "common", "dummyTemplates/endOfBraces");
1811 /*----------------------------------------------------------------
1812 02. Generate the comments string for the writeOnly registers.
1813 ----------------------------------------------------------------*/
1814 Translate(testFile, "common", "testProg/writeOnlyDefHead.c");
1815 for (i = 0; i < numRegisters; i++)
1816 if (registers[i].rar == AMWR) { /* is it is writeOnly? */
1817 TranslationSetRegName(registers[i].name);
1818 TranslationSetRegComm(registers[i].comment);
1819 Translate(testFile, "common",
1820 "testProg/common/regData.c");
1822 Translate(testFile, "common", "dummyTemplates/endOfBraces");
1824 /*-------------------------------------------------------------
1825 03. Generate the comments string for Service Registers.
1826 -------------------------------------------------------------*/
1827 Translate(testFile, "common", "testProg/serviceDefHead.c");
1828 for (i = 0; i < GetSrvRegNum(); i++) {
1829 TranslationSetRegName(srv_ioctl[i].name);
1830 TranslationSetRegComm(srv_ioctl[i].comment);
1831 Translate(testFile, "common", "testProg/common/regData.c");
1833 Translate(testFile, "common", "dummyTemplates/endOfBraces");
1837 * @brief Generate the last portion of the driver's test program.
1839 * @param registers -- register description
1840 * @param blocks -- block description
1841 * @param numRegisters -- register amount
1842 * @param testFile -- open file descriptor
1844 * It produces a sub menu for each of the defined blocks and for the extraneous
1845 * variables block.
1847 * @return void
1849 static void BuildTestProgSubMenus(RegisterDef_t * registers,
1850 BlockDef_t * blocks, int numRegisters,
1851 FILE * testFile)
1853 int i, j, count, blockStart, endOfBlock;
1855 TranslationReset();
1857 /*=================00. Generate WriteOnly Registers sub menu.==============*/
1858 Translate(testFile, "common", "testProg/writeOnlyMenuHead.c");
1859 if (!HasWriteOnly(registers, numRegisters))
1860 Translate(testFile, "common", "testProg/writeOnlyNO.c");
1861 else {
1862 /* Add a menu item for each extraneous variable that's
1863 been defined */
1864 Translate(testFile, "common", "testProg/common/menuHead.c");
1865 count = TST_PROG_SUB_MENU_FIRST_ENTRY;
1867 for (i = 0; i < numRegisters; i++)
1868 if (registers[i].rar == AMWR) {
1869 /* is it is writeOnly reg? */
1870 TranslationSetRegName(registers[i].name);
1872 /* read */
1873 TranslationSetPlainNum(count++);
1874 Translate(testFile, "common",
1875 "testProg/common/menuReadEntry.c");
1878 Translate(testFile, "common", "testProg/common/menuFoot.c");
1879 Translate(testFile, "common", "testProg/writeOnlyCaseHead.c");
1880 count = TST_PROG_SUB_MENU_FIRST_ENTRY;
1882 for (i = 0; i < numRegisters; i++)
1883 if (registers[i].rar == AMWR) {
1884 /* is it is writeOnly? */
1885 TranslationSetRegId(registers[i].upperName);
1887 /* read */
1888 TranslationSetPlainNum(count++);
1889 TranslationSetFancyString("Get");
1890 Translate(testFile, "common",
1891 "testProg/common/caseGetSet.c");
1893 Translate(testFile, "common", "testProg/common/caseEnd.c");
1896 /*=================01. Generate Extraneous Variable sub menu.==============*/
1897 Translate(testFile, "common", "testProg/common/extraneousMenuHead.c");
1898 if (!HasExtraneous(registers, numRegisters))
1899 /* If there were not any extraneous variables then generate
1900 code to alert the test program's user that there aren't any
1901 extra variables. If there were extraneous variables then
1902 produce the case statments that should accompany the menu
1903 items. */
1904 Translate(testFile, "common", "testProg/common/extraneousNO.c");
1905 else {
1906 /* Add a menu item for each extraneous variable that's been
1907 defined */
1908 Translate(testFile, "common", "testProg/common/menuHead.c");
1909 count = TST_PROG_SUB_MENU_FIRST_ENTRY;
1911 for (i = 0; i < numRegisters; i++)
1912 if (registers[i].rar == AMEX) {
1913 /* is it is extraneous? */
1914 TranslationSetRegName(registers[i].name);
1916 /* read */
1917 TranslationSetPlainNum(count++);
1918 Translate(testFile, "common",
1919 "testProg/common/menuReadEntry.c");
1921 /* write */
1922 TranslationSetPlainNum(count++);
1923 Translate(testFile, "common",
1924 "testProg/common/menuWriteEntry.c");
1926 Translate(testFile, "common", "testProg/common/menuFoot.c");
1927 Translate(testFile, "common",
1928 "testProg/common/extraneousCaseHead.c");
1929 count = TST_PROG_SUB_MENU_FIRST_ENTRY;
1931 for (i = 0; i < numRegisters; i++)
1932 if (registers[i].rar == AMEX) {
1933 /* is it is extraneous? */
1934 TranslationSetRegId(registers[i].upperName);
1936 /* read */
1937 TranslationSetPlainNum(count++);
1938 TranslationSetFancyString("Get");
1939 Translate(testFile, "common",
1940 "testProg/common/caseGetSet.c");
1942 /* write */
1943 TranslationSetPlainNum(count++);
1944 TranslationSetFancyString("Set");
1945 Translate(testFile, "common",
1946 "testProg/common/caseGetSet.c");
1948 Translate(testFile, "common", "testProg/common/caseEnd.c");
1951 /*=========02. Generate Service Registers sub menu.====================*/
1952 Translate(testFile, "common", "testProg/serviceMenuHead.c");
1953 Translate(testFile, "common", "testProg/common/menuHead.c");
1954 count = TST_PROG_SUB_MENU_FIRST_ENTRY;
1956 for (i = 0; i < GetSrvRegNum(); i++) {
1957 TranslationSetRegName(srv_ioctl[i].name);
1958 switch (srv_ioctl[i].rar) {
1959 case AMRD: /* 'r' */
1960 TranslationSetPlainNum(count++);
1961 Translate(testFile, "common",
1962 "testProg/common/menuReadEntry.c");
1963 break;
1964 case AMWR: /* 'w' */
1965 TranslationSetPlainNum(count++);
1966 Translate(testFile, "common",
1967 "testProg/common/menuWriteEntry.c");
1968 break;
1969 case (AMRD | AMWR): /* 'rw' */
1970 TranslationSetPlainNum(count++);
1971 Translate(testFile, "common",
1972 "testProg/common/menuReadEntry.c");
1973 TranslationSetPlainNum(count++);
1974 Translate(testFile, "common",
1975 "testProg/common/menuWriteEntry.c");
1976 break;
1977 default:
1978 /* it's not an error, just this service register
1979 is not r/w */
1980 break;
1983 Translate(testFile, "common", "testProg/common/menuFoot.c");
1984 Translate(testFile, "common", "testProg/serviceCaseHead.c");
1985 count = TST_PROG_SUB_MENU_FIRST_ENTRY;
1987 for (i = 0; i < GetSrvRegNum(); i++) {
1988 TranslationSetRegId(srv_ioctl[i].name);
1989 switch (srv_ioctl[i].rar) {
1990 case AMRD: /* 'r' */
1991 TranslationSetPlainNum(count++);
1992 TranslationSetFancyString("Get");
1993 Translate(testFile, "common",
1994 "testProg/common/caseGetSet.c");
1995 break;
1996 case AMWR: /* 'w' */
1997 TranslationSetPlainNum(count++);
1998 TranslationSetFancyString("Set");
1999 Translate(testFile, "common",
2000 "testProg/common/caseGetSet.c");
2001 break;
2002 case (AMRD | AMWR): /* 'rw' */
2003 TranslationSetPlainNum(count++);
2004 TranslationSetFancyString("Get");
2005 Translate(testFile, "common",
2006 "testProg/common/caseGetSet.c");
2008 TranslationSetPlainNum(count++);
2009 TranslationSetFancyString("Set");
2010 Translate(testFile, "common",
2011 "testProg/common/caseGetSet.c");
2012 break;
2013 default:
2014 /* it's not an error, just this service register
2015 is not r/w */
2016 break;
2019 Translate(testFile, "common", "testProg/common/caseEnd.c");
2021 /*=====03. Now generate sub menus for each of the defined blocks.==========*/
2022 endOfBlock = TRUE;
2024 for (i = 0; i < numRegisters; i++)
2025 if (registers[i].rar != AMEX) { /* skip extraneous registers */
2026 if (endOfBlock) {
2027 TranslationSetFancyNum(registers[i].blockP->
2028 blockID);
2029 TranslationSetPlainNum(registers[i].blockP->
2030 blockID);
2031 Translate(testFile, "common",
2032 "testProg/common/blockMenuHead.c");
2033 Translate(testFile, "common",
2034 "testProg/common/menuHead.c");
2035 count = TST_PROG_SUB_MENU_FIRST_ENTRY;
2036 blockStart = i;
2038 TranslationSetRegName(registers[i].name);
2039 switch (registers[i].rar) {
2040 case AMRD: /* 'r' */
2041 TranslationSetPlainNum(count++);
2042 Translate(testFile, "common",
2043 "testProg/common/menuReadEntry.c");
2044 break;
2045 case AMWR: /* 'w' */
2046 TranslationSetPlainNum(count++);
2047 Translate(testFile, "common",
2048 "testProg/common/menuWriteEntry.c");
2049 break;
2050 case (AMWR | AMRD): /* 'rw' */
2051 TranslationSetPlainNum(count++);
2052 Translate(testFile, "common",
2053 "testProg/common/menuReadEntry.c");
2055 TranslationSetPlainNum(count++);
2056 Translate(testFile, "common",
2057 "testProg/common/menuWriteEntry.c");
2058 break;
2059 default:
2060 FATAL_ERR();
2061 break;
2064 if (i == numRegisters - 1)
2065 endOfBlock = TRUE;
2066 else if (registers[i].blockP->blockID !=
2067 registers[i + 1].blockP->blockID)
2068 endOfBlock = TRUE;
2069 else
2070 endOfBlock = FALSE;
2072 if (endOfBlock) { /* now 'switch' can be generated */
2073 Translate(testFile, "common",
2074 "testProg/common/menuFoot.c");
2075 Translate(testFile, "common",
2076 "testProg/common/blockCaseHead.c");
2077 count = TST_PROG_SUB_MENU_FIRST_ENTRY;
2079 for (j = blockStart; j <= i; j++) {
2080 TranslationSetRegId(registers[j].
2081 upperName);
2082 switch (registers[j].rar) {
2083 case AMRD: /* 'r' */
2084 TranslationSetPlainNum(count++);
2085 TranslationSetFancyString
2086 ("Get");
2087 Translate(testFile, "common",
2088 "testProg/common/"
2089 "caseGetSet.c");
2090 break;
2091 case AMWR: /* 'w' */
2092 TranslationSetPlainNum(count++);
2093 TranslationSetFancyString
2094 ("Set");
2095 Translate(testFile, "common",
2096 "testProg/common/"
2097 "caseGetSet.c");
2098 break;
2099 case (AMWR | AMRD): /* 'rw' */
2100 TranslationSetPlainNum(count++);
2101 TranslationSetFancyString
2102 ("Get");
2103 Translate(testFile, "common",
2104 "testProg/common/"
2105 "caseGetSet.c");
2107 TranslationSetPlainNum(count++);
2108 TranslationSetFancyString
2109 ("Set");
2110 Translate(testFile, "common",
2111 "testProg/common/"
2112 "caseGetSet.c");
2113 break;
2114 default:
2115 FATAL_ERR();
2116 break;
2118 } /* end of for */
2119 Translate(testFile, "common",
2120 "testProg/common/caseEnd.c");
2121 } /* end of if */
2122 } /* end of for */
2126 * @brief Create major header files that are common for all VME/DRM drivers.
2128 static void BuildGeneralHeaderFiles(void)
2130 int cntr;
2131 int constCounter; /* */
2132 FILE *fp;
2133 char *bus = TranslationGetBus(); /* 'VME' or 'DRM' */
2135 /* set general constants */
2136 fp = OpenFile(EXACT_FT, LOC_GENERAL, "%s/GeneralHeader.h", DG_INC_DIR);
2137 TranslationSetPrecision(MAX_STR);
2138 TranslationSetDDDNum(MIN_STR);
2139 TranslationSetPlainNum(NAME_LEN);
2140 TranslationSetRegDepth(MAX_REG);
2141 TranslationSetIntNum(MAX_BLK);
2142 TranslationSetExtraNum(NO_ADDRESS);
2143 TranslationSetHexNum(NO_LUN);
2144 Translate(fp, "common", "header/generalHeader.h");
2145 fclose(fp);
2147 /* header for driver and simulator. Differs for VME/PCI buses. */
2148 fp = OpenFile(EXACT_FT, LOC_GENERAL, "%s/ModuleHeader.h", DG_INC_DIR);
2149 Translate(fp, bus, "header/generalHeader.h");
2150 fclose(fp);
2152 /* register description is placed here */
2153 fp = OpenFile(EXACT_FT, LOC_GENERAL, "%s/RegDesc.h", DG_INC_DIR);
2154 Translate(fp, "common", "header/regDesc.h");
2155 fclose(fp);
2157 /* seed Linux Kernel List */
2158 fp = OpenFile(EXACT_FT, LOC_GENERAL, "%s/lklist.h", DG_INC_DIR);
2159 Translate(fp, "common", "header/lklist.h");
2160 fclose(fp);
2162 /* VMEbus Address Modifier Codes */
2163 fp = OpenFile(EXACT_FT, LOC_GENERAL, "%s/vme_am.h", DG_INC_DIR);
2164 Translate(fp, "../include", "vme_am.h");
2165 fclose(fp);
2167 /* port operations for Lynx */
2168 fp = OpenFile(EXACT_FT, LOC_GENERAL, "%s/port_ops_lynx.h", DG_INC_DIR);
2169 Translate(fp, "common", "header/port_ops_lynx.h");
2170 fclose(fp);
2172 /* port operations for Linux */
2173 fp = OpenFile(EXACT_FT, LOC_GENERAL, "%s/port_ops_linux.h", DG_INC_DIR);
2174 Translate(fp, "common", "header/port_ops_linux.h");
2175 fclose(fp);
2177 /* extra swap operations for Linux */
2178 fp = OpenFile(EXACT_FT, LOC_GENERAL, "%s/swab-extra-linux.h",
2179 DG_INC_DIR);
2180 Translate(fp, "common", "header/swab-extra-linux.h");
2181 fclose(fp);
2183 /* service registers ioctl numbers */
2184 fp = OpenFile(EXACT_FT, LOC_GENERAL, "%s/ServiceRegIoctl.h",
2185 DG_INC_DIR);
2186 Translate(fp, "common", "header/srvHead.h");
2187 TranslationSetFancyString("IOCTL_BASE"); /* setup base number for the
2188 service ioctl numbers */
2190 for (cntr = 0, constCounter = 0; cntr < GetSrvRegNum(); cntr++) {
2191 switch (srv_ioctl[cntr].rar) {
2192 case AMRD: /* 'r' */
2193 TranslationSetPlainNum(constCounter++);
2194 TranslationSetIoctlConst("GET", srv_ioctl[cntr].name);
2195 Translate(fp, "common", "header/ioctlConst.h");
2196 break;
2197 case AMWR: /* 'w' */
2198 TranslationSetPlainNum(constCounter++);
2199 TranslationSetIoctlConst("SET", srv_ioctl[cntr].name);
2200 Translate(fp, "common", "header/ioctlConst.h");
2201 break;
2202 case (AMWR | AMRD): /* 'rw' */
2203 TranslationSetPlainNum(constCounter++);
2204 TranslationSetIoctlConst("GET", srv_ioctl[cntr].name);
2205 Translate(fp, "common", "header/ioctlConst.h");
2207 TranslationSetPlainNum(constCounter++);
2208 TranslationSetIoctlConst("SET", srv_ioctl[cntr].name);
2209 Translate(fp, "common", "header/ioctlConst.h");
2210 break;
2211 default:
2212 /* special srv register that has ioctl entry,
2213 but it's not a 'r/w' register */
2214 TranslationSetPlainNum(constCounter++);
2215 TranslationSetIoctlConst("", srv_ioctl[cntr].name);
2216 Translate(fp, "common", "header/ioctlConst.h");
2217 break;
2221 TranslationSetPlainNum(constCounter);
2222 Translate(fp, "common", "header/srvFoot.h");
2223 fclose(fp);
2225 /* service registers ID enum */
2226 fp = OpenFile(EXACT_FT, LOC_GENERAL, "%s/ServiceRegId.h", DG_INC_DIR);
2227 Translate(fp, "common", "header/srvIdHead.h");
2229 for (cntr = 0, constCounter = 0; cntr < GetSrvRegNum(); cntr++) {
2230 TranslationSetRegId(srv_ioctl[cntr].name);
2231 TranslationSetRegComm(srv_ioctl[cntr].comment);
2232 TranslationSetFancyString(rar2mode(srv_ioctl[cntr].rar));
2233 TranslationSetDummyString(itoa(constCounter++, 10));
2234 Translate(fp, "common", "header/regIdEnumIndexed.h");
2237 /* set last service regID description */
2238 TranslationSetRegName(srv_ioctl[cntr].name);
2239 TranslationSetRegComm(srv_ioctl[cntr].comment);
2240 TranslationSetDummyString(itoa(constCounter, 10));
2241 Translate(fp, "common", "header/srvIdFoot.h");
2242 fclose(fp);
2246 * @brief Generate general libraries source code, wich are @b DriverAccess,
2247 * @b Ioconfig and @b extra-lynx
2249 * @param none
2251 * DriverAccess library enables user to use @e DaGetElement(),
2252 * @e DaSetElement() and many other functions for register accessing.
2254 * Ioconfig library enables user to access driver by means of @e ioconfig
2255 * calls, that uses a direct memory access mechanism for accessing.
2257 * xtra-lynx -- imports such handy functions as vsnprintf, asprintf etc...
2258 * into user-space apps.
2260 * @return void
2262 static void BuildGeneralLibraries()
2264 FILE *fd;
2265 char *bus = TranslationGetBus(); /* 'VME' or 'DRM' */
2266 char *tstr = ctime(&mod_creation_time);
2268 tstr[strlen(tstr) - 1] = 0; /* get rid of '\n' */
2270 /* driverAccess library source code */
2271 /* generate '.h' file */
2272 fd = OpenFile(EXACT_FT, LOC_GENERAL, "%s/dal.h", DG_INC_DIR);
2273 Translate(fd, bus, "lib/drvrAccess/DrvrAccess.h");
2274 fclose(fd);
2276 /* generate '.c' files */
2277 fd = OpenFile(EXACT_FT, LOC_GENERAL, "%s/dal.c", DAL_DIR);
2279 /* set DAL generation time */
2280 TranslationSetHexNum(mod_creation_time);
2281 TranslationSetComment(tstr);
2283 /* DAL mainframe */
2284 Translate(fd, bus, "lib/drvrAccess/DrvrAccess.c");
2285 fclose(fd);
2287 /* Linux DMA support */
2288 fd = OpenFile(EXACT_FT, LOC_GENERAL, "%s/dma.c", DAL_DIR);
2289 Translate(fd, bus, "lib/drvrAccess/dma.c");
2290 fclose(fd);
2292 fd = OpenFile(EXACT_FT, LOC_GENERAL, "%s/swa.h", DG_INC_DIR);
2293 Translate(fd, bus, "lib/drvrAccess/swa.h");
2294 fclose(fd);
2297 /* mmap access for Lynx */
2298 fd = OpenFile(EXACT_FT, LOC_GENERAL, "%s/IoconfAccess.c", DAL_DIR);
2299 Translate(fd, bus, "lib/drvrAccess/ioconf.c");
2300 fclose(fd);
2302 /* xtra-lynx library -- handy function for lynx user-space */
2303 fd = OpenFile(EXACT_FT, LOC_GENERAL, "%s/lynx-extra.c", DAL_DIR);
2304 Translate(fd, bus, "lib/drvrAccess/lynx-extra.c");
2305 fclose(fd);
2309 * @brief Build Device driver installation/uninstallation program source code.
2311 * @param none
2313 * @return void
2315 static void BuildGeneralInstallProgram()
2317 FILE *fd;
2318 char *bus = TranslationGetBus(); /* 'VME' or 'DRM' */
2320 /* generate install program '.h' file */
2321 fd = OpenFile(EXACT_FT, LOC_GENERAL, "%s/modinst.h", DG_INC_DIR);
2322 Translate(fd, bus, "installProg/modinst.h");
2323 fclose(fd);
2325 /* generate install program '.c' file */
2326 fd = OpenFile(EXACT_FT, LOC_GENERAL, "%s/modinst.c", INST_RM_DIR);
2327 Translate(fd, bus, "installProg/modinst.c");
2328 fclose(fd);
2330 /* generate deinstall program '.h' file */
2331 fd = OpenFile(EXACT_FT, LOC_GENERAL, "%s/moduninst.h", DG_INC_DIR);
2332 Translate(fd, bus, "installProg/moduninst.h");
2333 fclose(fd);
2335 /* generate deinstall program '.c' file */
2336 fd = OpenFile(EXACT_FT, LOC_GENERAL, "%s/moduninst.c", INST_RM_DIR);
2337 Translate(fd, bus, "installProg/moduninst.c");
2338 fclose(fd);
2340 /* add utilities */
2341 fd = OpenFile(EXACT_FT, LOC_GENERAL, "%s/utils.c", INST_RM_DIR);
2342 Translate(fd, bus, "installProg/utils.c");
2343 fclose(fd);
2345 fd = OpenFile(EXACT_FT, LOC_GENERAL, "%s/utils.h", DG_INC_DIR);
2346 Translate(fd, bus, "installProg/utils.h");
2347 fclose(fd);
2349 /* Lynx-specific utils */
2350 fd = OpenFile(EXACT_FT, LOC_GENERAL, "%s/utils-lynx.c", INST_RM_DIR);
2351 Translate(fd, bus, "installProg/utils-lynx.c");
2352 fclose(fd);
2354 /* Linux-specific utils */
2355 fd = OpenFile(EXACT_FT, LOC_GENERAL, "%s/utils-linux.c", INST_RM_DIR);
2356 Translate(fd, bus, "installProg/utils-linux.c");
2357 fclose(fd);
2359 /* Lynx API, needed for linux */
2360 fd = OpenFile(EXACT_FT, LOC_GENERAL, "%s/extra-linux.c", INST_RM_DIR);
2361 Translate(fd, bus, "installProg/extra-linux.c");
2362 fclose(fd);
2364 fd = OpenFile(EXACT_FT, LOC_GENERAL, "%s/extra-linux.h", DG_INC_DIR);
2365 Translate(fd, bus, "installProg/extra-linux.h");
2366 fclose(fd);
2370 * @brief Build-up makefiles that are located in @e general directory.
2372 * @param none
2374 * They contains install/uninstall programs, DALib and header files that are
2375 * common to all generated drivers.
2377 * @return void
2379 static void BuildGeneralMakefiles()
2381 FILE *mkfd;
2383 /* Base Makefile */
2384 mkfd = OpenFile(EXACT_FT, LOC_GENERAL, "Makefile.base");
2385 Translate(mkfd, "common", "makefiles/Makefile.base");
2386 fclose(mkfd);
2388 /* "Which dirs to compile" Makefile */
2389 mkfd = OpenFile(EXACT_FT, LOC_GENERAL, "Makefile");
2390 TranslationSetFreeFormat("%s", DG_INC_DIR);
2391 TranslationSetString(DAL_DIR);
2392 TranslationSetComment(INST_RM_DIR);
2393 Translate(mkfd, "common", "makefiles/MakefileShared");
2394 fclose(mkfd);
2396 /* Include Makefile */
2397 mkfd = OpenFile(EXACT_FT, LOC_GENERAL, "%s/Makefile", DG_INC_DIR);
2398 Translate(mkfd, "common", "makefiles/includeGeneral.mk");
2399 fclose(mkfd);
2401 /* Libraries Makefile */
2402 mkfd = OpenFile(EXACT_FT, LOC_GENERAL, "%s/Makefile", DAL_DIR);
2404 Translate(mkfd, "common", "makefiles/libShared.mk");
2405 fclose(mkfd);
2407 /* Install program Makefile */
2408 mkfd = OpenFile(EXACT_FT, LOC_GENERAL, "%s/Makefile", INST_RM_DIR);
2409 TranslationSetString(DG_INC_DIR);
2410 Translate(mkfd, "common", "makefiles/instProg.mk");
2411 fclose(mkfd);
2413 mkfd = OpenFile(EXACT_FT, LOC_GENERAL, "%s/deliver.mk", INST_RM_DIR);
2414 Translate(mkfd, "common", "makefiles/deliver.mk");
2415 fclose(mkfd);
2419 * @brief
2421 * @param none
2423 * @return void
2425 static void BuildGeneralScripts(void)
2427 FILE *mkfd;
2429 mkfd = OpenFile(EXACT_FT, LOC_GENERAL, UTIL_CP_USR_PT_GLOB);
2430 Translate(mkfd, "common", UTIL_CP_USR_PT_GLOB);
2431 fchmod(fileno(mkfd), 0755); /* set new access rights */
2432 fclose(mkfd);
2436 * @brief Checks if register description obtained from the data base contains
2437 * any extraneous registers.
2439 * @param registers -- register description
2440 * @param numRegisters -- register amount
2442 * @return amount of extraneous registers
2444 static int HasExtraneous(RegisterDef_t * registers, int numRegisters)
2446 int amount = 0;
2447 int cntr;
2449 for (cntr = 0; cntr < numRegisters; cntr++)
2450 if (registers[cntr].rar == AMEX)
2451 amount++;
2453 return (amount);
2457 * @brief Checks if register description obtained from the data base contains
2458 * any writeOnly registers.
2460 * @param registers -- register description
2461 * @param numRegisters -- register amount
2463 * @return amount of writeonly registers.
2465 static int HasWriteOnly(RegisterDef_t * registers, int numRegisters)
2467 static int amount = -1;
2468 int i;
2470 if (amount == -1) {
2471 amount++;
2472 for (i = 0; i < numRegisters; i++)
2473 if (registers[i].rar == AMWR)
2474 amount++;
2477 return (amount);