4 * @brief Pulling everything together.
6 * @author Copyright (c) 2004 - 2009 CERN. Georgievskiy Yury, Alain Gagnaire
8 * @date Created on 27/02/2004
10 * Device Driver Generator (aka DriverGen) tool designed to produce
11 * device drivers for a given architecture based on an abstract description
12 * of a piece of hardware.
14 #define _GNU_SOURCE /* asprintf rocks */
16 #include "driverGen.h"
17 #include "utilities.h"
18 #include "serviceOptions.h"
19 #include "dg-version.h"
20 #include "dg-git-lib.h"
22 struct mdescr dgmd
= { 0 }; /* Driver-Gen Module Description */
24 bool verboseMode
; /* denotes verbose driver generation */
25 static dgopt genOpt
; /* possible command line options */
26 static srvarg glob_srv_arg
; /* possible service option arguments */
27 char *driverName
; /* Driver Name. Exactly as in the DataBase */
28 char *busType
; /* bus type. 'vme' or 'pci' */
29 time_t mod_creation_time
; /* driver creation time of the currently
33 static char *allBuses
[] = {
41 /* supported command line options */
42 static struct option allLongOptions
[] = {
43 { "git", no_argument
, NULL
, 'g' },
44 { "gall", no_argument
, NULL
, 'a' },
45 { "ginfo", no_argument
, NULL
, 'i' },
46 { "general", required_argument
, NULL
, 'e' },
47 { "verbose", no_argument
, NULL
, 'n' },
48 { "srv", required_argument
, NULL
, 's' }, /* see 'serviceOptions.h'
49 for more information */
50 { "dir", required_argument
, NULL
, 'd' },
51 { "version", no_argument
, NULL
, 'v' },
52 { "help", no_argument
, NULL
, 'h' },
55 .has_arg
= no_argument
, /* 0 */
61 static int CheckAndPrepareRegs(RegisterDef_t
*, int, VmeInfo_t
*);
62 static int CheckAndPrepareBlocks(BlockDef_t
*, int);
63 static void SortRegisters(RegisterDef_t
*, VmeInfo_t
*, int, int);
64 static int LessThan(RegisterDef_t
*, RegisterDef_t
*);
65 static int GreaterThan(RegisterDef_t
*, RegisterDef_t
*);
66 static void SortBlocks(BlockDef_t
*, int, int);
67 static bool CheckBusType(char *);
68 static void DisplayUsage(char *);
69 static void ParseProgArgs(int, char *[], struct mdescr
*);
70 static void free_md(struct mdescr
*);
72 int main(int argc
, char *argv
[], char *envp
[])
77 RegisterDef_t registers
[MAX_REG
] = { {0} };
78 BlockDef_t blocks
[MAX_BLK
] = { {0} };
82 /* Init default parameters */
83 vmeInfo
.CheckRegister
= -1; /* no checking register */
84 verboseMode
= FALSE
; /* by default - no verbose mode */
86 ParseProgArgs(argc
, argv
, &dgmd
); /* check if provided params are valid */
87 time(&mod_creation_time
);
88 printf("%s <vers. %s> started on %s\n", basename(argv
[0]), dg_version
,
89 ctime(&mod_creation_time
));
91 /* init global template values for further use */
92 TranslationInit(driverName
, busType
);
94 /* if only general shared code should be build */
95 if (genOpt
== OPT_G_SHARED
) {
97 printf("%s: All done.\n", basename(argv
[0]));
101 /* if it's one of the service calls */
102 if (genOpt
== OPT_G_SERVICE
) {
103 if (ProcessSrvOpt(glob_srv_arg
, basename(argv
[0]))) {
104 printf("%s: service option processing fails\n",
108 printf("%s: service option processing done.\n",
114 /* get block configuration from database */
115 if (!(numBlocks
= GetBlockConfig(driverName
, blocks
, argv
[0]))) {
116 fprintf(stderr
, "%s No Blocks found for %s Module\n", ERROR_MSG
,
121 /* check if block configuration is correct */
122 if (CheckAndPrepareBlocks(blocks
, numBlocks
) != DRIVER_GEN_OK
)
125 /* get register configuration from database */
126 numRegisters
= GetRegisterConfig(driverName
, registers
, blocks
,
129 fprintf(stderr
, "%s No Registers found for %s Module\n",
130 ERROR_MSG
, driverName
);
134 /* check if register configuration is correct */
135 if (CheckAndPrepareRegs(registers
, numRegisters
, &vmeInfo
) !=
139 /* we need to compute block sizes and their register amount */
140 set_extra_block_data(registers
);
142 /* get general board information from the database */
143 if (!strcmp(TranslationGetBus(), "VME"))
144 result
= GetVmeInfo(driverName
, &vmeInfo
);
146 result
= GetPciInfo(driverName
, &pciInfo
);
149 exit(EXIT_FAILURE
); /* 1 */
151 /* now we can start Driver/Simulator code generation */
152 printf("Creating %s source code directory.\n", driverName
);
154 /* setup Master installation and Module source directories */
158 if (!strcmp(TranslationGetBus(), "VME")) { /* we need VME driver */
161 GenerateVmeDriver(registers
, numRegisters
, blocks
,
162 numBlocks
, &vmeInfo
);
165 case OPT_G_ALL
: /* generate all, include user-defined files */
166 GenerateVmeDriver(registers
, numRegisters
, blocks
,
167 numBlocks
, &vmeInfo
);
169 case OPT_G_INFO
: /* generate only info files */
170 GenerateVmeInfoFile(registers
, numRegisters
, blocks
,
171 numBlocks
, &vmeInfo
);
175 break; /* not reached */
177 } else { /* we need PCI driver */
180 GenerateDrmDriver(registers
, numRegisters
, blocks
,
181 numBlocks
, &pciInfo
);
184 case OPT_G_ALL
: /* generate all, include user-defined files */
185 GenerateDrmDriver(registers
, numRegisters
, blocks
,
186 numBlocks
, &pciInfo
);
188 case OPT_G_INFO
: /* generate only install files */
189 /* TODO. Should be removed. */
190 GenerateDrmInstallFilesOLD(&pciInfo
, blocks
, numBlocks
);
194 break; /* not reached */
199 printf("All done.\n");
200 exit(EXIT_SUCCESS
); /* 0 */
204 * @brief Checks if module configuration is correct and supported.
206 * @param registers -- register description
207 * @param numRegisters -- register amount
208 * @param vmeInfo -- @b VME description
210 * @return DRIVER_GEN_OK - if configuration is ok.
211 * @return DRIVER_GEN_BAD - othervise.
213 static int CheckAndPrepareRegs(RegisterDef_t
* registers
, int numRegisters
,
217 int badConfig
= DRIVER_GEN_OK
;
218 int mappedAddr
= 0; /* checked address range */
219 int regDepth
; /* register depth, in elements */
221 for (i
= 0; i
< numRegisters
; i
++) { /* Sanitise register definition */
222 StrToLower(registers
[i
].size
);
223 StrToLower(registers
[i
].mode
);
224 registers
[i
].rar
= 0;
225 for (j
= 0; j
< strlen(registers
[i
].mode
); j
++) {
226 if (registers
[i
].mode
[j
] == 'w') {
227 registers
[i
].rar
|= AMWR
;
228 } else if (registers
[i
].mode
[j
] == 'r') {
229 registers
[i
].rar
|= AMRD
;
230 } else if (registers
[i
].mode
[j
] == 'e') {
231 registers
[i
].rar
|= AMEX
;
232 } else if (registers
[i
].mode
[j
] == 'c') {
233 vmeInfo
->CheckRegister
= i
;
235 badConfig
= DRIVER_GEN_BAD
;
236 fprintf(stderr
, "%s Register '%s' has unknown"
237 " access mode '%c'\n",
238 ERROR_MSG
, registers
[i
].name
,
239 registers
[i
].mode
[j
]);
243 strcpy(registers
[i
].upperName
, registers
[i
].name
);
244 StrToUpper(registers
[i
].upperName
);
246 if (!strcmp(registers
[i
].size
, "char"))
247 registers
[i
].regSize
= SZCHAR
;
248 else if (!strcmp(registers
[i
].size
, "short"))
249 registers
[i
].regSize
= SZSHORT
;
250 else if (!strcmp(registers
[i
].size
, "long"))
251 registers
[i
].regSize
= SZLONG
;
253 badConfig
= DRIVER_GEN_BAD
;
254 fprintf(stderr
, "%s Register '%s' has incorrect size"
256 ERROR_MSG
, registers
[i
].name
,
260 /* Check if the data is valid */
261 if (registers
[i
].timeLoop
< 0) {
262 badConfig
= DRIVER_GEN_BAD
;
263 fprintf(stderr
, "%s Register '%s' has a negative"
265 ERROR_MSG
, registers
[i
].name
,
266 registers
[i
].timeLoop
);
269 for (j
= 0; j
< strlen(registers
[i
].name
); j
++)
270 if (isspace(registers
[i
].name
[j
]))
271 /* replace wite spaces with underscore */
272 registers
[i
].name
[j
] = '_';
274 for (j
= i
+ 1; j
< numRegisters
; j
++)
275 if (!strcmp(registers
[i
].name
, registers
[j
].name
)) {
276 badConfig
= DRIVER_GEN_BAD
;
277 fprintf(stderr
, "%s Register definitions %d"
278 " and %d share the name \"%s\"\n",
279 ERROR_MSG
, i
, j
, registers
[i
].name
);
282 if (registers
[i
].rar
> AMEX
) {
283 fprintf(stderr
, "%s Register '%s' has a conflicting"
284 " access mode '%s'\n",
285 ERROR_MSG
, registers
[i
].name
,
287 sprintf(registers
[i
].mode
, "e");
288 registers
[i
].rar
= AMEX
;
291 if ((!registers
[i
].blockP
)) {
292 badConfig
= DRIVER_GEN_BAD
;
293 fprintf(stderr
, "%s Register '%s' doesn't belong to"
295 ERROR_MSG
, registers
[i
].name
);
298 if (registers
[i
].offset
< 0) {
299 badConfig
= DRIVER_GEN_BAD
;
300 fprintf(stderr
, "%s Register '%s' has negative offset"
302 ERROR_MSG
, registers
[i
].name
,
303 registers
[i
].offset
);
307 if (badConfig
== DRIVER_GEN_BAD
)
310 /* sort registers by their address */
311 SortRegisters(registers
, vmeInfo
, 0, numRegisters
- 1);
313 for (i
= 0; i
< numRegisters
- 1; i
++) {
315 if (registers
[i
].depth
<= 0)
318 regDepth
= registers
[i
].depth
;
320 /* check registers that belong to the same block only */
321 if (registers
[i
].blockP
->blockID
==
322 registers
[i
+ 1].blockP
->blockID
) {
323 /* check if there is duplicate register addresses
325 if (registers
[i
].offset
== registers
[i
+ 1].offset
) {
326 badConfig
= DRIVER_GEN_BAD
;
327 fprintf(stderr
, "%s Registers '%s' and '%s' in"
328 " Block#%d have the same offset %#x\n",
329 ERROR_MSG
, registers
[i
].name
,
330 registers
[i
+ 1].name
,
331 registers
[i
].blockP
->blockID
,
332 registers
[i
].offset
);
335 registers
[i
].offset
+
336 registers
[i
].regSize
* regDepth
;
337 if (mappedAddr
> registers
[i
+ 1].offset
) {
338 fprintf(stderr
, "%s Overlapping between '%s'"
339 " and '%s' register massives\n"
340 "\tdetected in Block#%d. Incorrect "
341 "device memory mapping. Try to "
342 "change\n\tmemory layout in the Data"
344 ERROR_MSG
, registers
[i
].name
,
345 registers
[i
+ 1].name
,
346 registers
[i
].blockP
->blockID
);
347 badConfig
= DRIVER_GEN_BAD
;
354 if (badConfig
== DRIVER_GEN_BAD
)
357 /* Check if device checking address is provided */
358 if (vmeInfo
->CheckRegister
== -1) {
359 fprintf(stderr
, "%sChecking Register is NOT provided!\n"
360 " Module availability will NOT be checked"
361 " during device driver\n installation!\n\n",
363 sleep(2); /* let user see it */
370 * @brief Checks if block configuration is correct and supported.
372 * @param blocks -- block description
373 * @param numBlocks -- block amount
375 * @return DRIVER_GEN_OK - if configuration is ok.
376 * @return DRIVER_GEN_BAD - othervise.
378 static int CheckAndPrepareBlocks(BlockDef_t
* blocks
, int numBlocks
)
381 int configState
= DRIVER_GEN_OK
;
383 for (i
= 0; i
< numBlocks
; i
++) {
384 if (blocks
[i
].blockID
< 0) {
385 fprintf(stderr
, "%s GetBlockConfig() has returned a"
386 " record with a negative block number\n",
388 configState
= DRIVER_GEN_BAD
;
391 if ((blocks
[i
].blkBaseAddr
< 1) ||
392 (blocks
[i
].blkBaseAddr
> 2)) {
393 fprintf(stderr
, "%s Block#%d is associated with"
394 " invalid base address value '%d'\n",
395 ERROR_MSG
, blocks
[i
].blockID
,
396 blocks
[i
].blkBaseAddr
);
397 configState
= DRIVER_GEN_BAD
;
400 if (blocks
[i
].offset
< 0) {
401 fprintf(stderr
, "%s Block#%d has a negative offset"
403 ERROR_MSG
, blocks
[i
].blockID
);
404 configState
= DRIVER_GEN_BAD
;
408 if (configState
== DRIVER_GEN_OK
) {
409 SortBlocks(blocks
, 0, numBlocks
- 1);
410 for (i
= 0; i
< numBlocks
- 1; i
++)
411 if (blocks
[i
].blockID
== blocks
[i
+ 1].blockID
) {
412 fprintf(stderr
, "%s GetBlockConfig() has"
413 " returned two records with block ID's"
415 ERROR_MSG
, blocks
[i
].blockID
);
416 configState
= DRIVER_GEN_BAD
;
424 * @brief Sort registers by their block indexes && addresses.
426 * @param registers -- register description table
427 * @param vmeInfo -- VME description
428 * @param low -- lowest index
429 * @param high -- highest index
431 static void SortRegisters(RegisterDef_t
*registers
, VmeInfo_t
*vmeInfo
,
435 RegisterDef_t buffer
;
436 RegisterDef_t
*median
;
441 median
= ®isters
[low
];
443 while (right
>= low
) {
444 while (LessThan(&(registers
[left
]), median
))
447 while (GreaterThan(&(registers
[right
]), median
))
453 buffer
= registers
[left
];
454 registers
[left
] = registers
[right
];
455 registers
[right
] = buffer
;
457 /* move checking register index */
458 if (vmeInfo
->CheckRegister
== left
)
459 vmeInfo
->CheckRegister
= right
;
460 else if (vmeInfo
->CheckRegister
== right
)
461 vmeInfo
->CheckRegister
= left
;
467 SortRegisters(registers
, vmeInfo
, low
, right
);
468 SortRegisters(registers
, vmeInfo
, left
, high
);
473 * @brief Check if register a is smaller then register b
475 * @param a -- reg descr
476 * @param b -- reg descr
478 * @return 1 - if first regID is smaller then the second one.
479 * @return 0 - otherwise.
481 static int LessThan(RegisterDef_t
*a
, RegisterDef_t
*b
)
483 if (a
->blockP
->blockID
< b
->blockP
->blockID
)
485 else if ((a
->blockP
->blockID
== b
->blockP
->blockID
) &&
486 (a
->offset
< b
->offset
))
493 * @brief Check if register a is greater then register b
495 * @param a -- reg descr
496 * @param b -- reg descr
498 * @return 1 - if first regID is greater then the second one.
499 * @return 0 - otherwise.
501 static int GreaterThan(RegisterDef_t
*a
, RegisterDef_t
*b
)
503 if ((a
->blockP
->blockID
== b
->blockP
->blockID
)
504 && (a
->offset
== b
->offset
))
507 return (!LessThan(a
, b
));
511 * @brief Sort blocks by their index
513 * @param blocks -- block description
514 * @param low -- low block idx
515 * @param high -- high block idx
519 static void SortBlocks(BlockDef_t
*blocks
, int low
, int high
)
528 median
= &(blocks
[low
]);
530 while (right
>= low
) {
531 while (blocks
[left
].blockID
< median
->blockID
)
534 while (blocks
[right
].blockID
> median
->blockID
)
540 buffer
= blocks
[left
];
541 blocks
[left
] = blocks
[right
];
542 blocks
[right
] = buffer
;
547 SortBlocks(blocks
, low
, right
);
548 SortBlocks(blocks
, left
, high
);
553 * @brief Checks if the bus type parameter is correct.
555 * If it is not, than error is printed out on stderr.
557 * @param str -- string to check
559 * @return TRUE - if parameter is valid.
560 * @return FALSE - otherwise.
562 static bool CheckBusType(char *str
)
565 char **ptr
, errMsg
[64];
568 snprintf(errMsg
, sizeof(errMsg
), "Bus type \'%s\' not supported.\n",
572 if (!(strcmp(*ptr
, str
))) { /* option matches */
576 ptr
++; /* move pointer */
580 fprintf(stderr
, errMsg
); /* printout error message. */
586 * @brief Educate user
588 * @param progName -- program name
592 static void DisplayUsage(char *progName
)
594 progName
= basename(progName
);
595 printf("%s %s\n\n", progName
, dg_version
);
596 printf("Usage: %s <module_name> <bus> -g[it | all | info] "
597 "<-verbose> -d <root_dir>\n", progName
);
598 printf(" %s <-general> <bus>\n", progName
);
599 printf(" %s <-h> <--version> (to get help && version info)\n",
604 printf(" <module_name> %sCompulsory%s\n", WHITE_CLR
, END_CLR
);
605 printf(" It is the name of the module for which Driver/Simulator "
606 "should be generated.\n");
607 printf(" Should be exactly as in the DataBase. See DataBase for"
608 " more info about\n Module Names.\n\n");
611 printf(" <bus> %sCompulsory%s\n", WHITE_CLR
, END_CLR
);
612 printf(" Select the bus architecture supported by the card.\n");
613 printf(" Supported buses are 'pci' or 'vme'.\n\n");
615 /* '-g' mode description */
616 printf(" -g %sOptional%s\n"
617 " What to generate (if not provided -- default will be"
618 " used):\n", WHITE_CLR
, END_CLR
);
619 printf(" -g[all] %sDefault%s\n"
620 " Generate complete driver framework\n",
623 " Generate git-controlled Driver, i.e. user-defined files"
625 " only if driver directory does not yet exist (otherwise"
626 " user-defined files\n"
627 " left intact), driver dir name doesn't have time prefix,"
629 " performed. (All files, that've got \"UserDefined\""
630 " subword in their\n"
631 " name -- are considered to be user-defined files)\n");
633 " Generate only info file for current module.\n\n");
635 /* '-verbose' mode description */
636 printf(" <-verbose> %sOptional%s\n"
637 " This enables verbose driver/simulator source code"
639 " Useful for debugging purposes.\n\n", WHITE_CLR
, END_CLR
);
641 /* '-dir' mode description */
642 printf(" <-d> %sOptional%s\n"
643 " Change root directory, where generated driver source code"
645 " Default one is 'genDriverDeposit'\n\n",
648 /* '-general' mode description */
649 printf(" <-general> %sOptional%s\n", WHITE_CLR
, END_CLR
);
650 printf(" Normal users should ignore this option.\n If all that you"
651 " want - is to generate a Driver/Simulator framework for a\n"
652 " given module, and you didn't make any changes in"
653 " installation procedure\n and library code (that is usially"
654 " the case), than you should ignore\n this option. Only"
655 " general purpose files (i.e. identical for all types of \n"
656 " Driver/Simulator) will be generated. These are module"
657 " Driver/Simulator\n installation and unistallaion programs,"
658 " 'DriverAccess' library and general\n header files. Normally,"
659 " general purpose part should be rebuild by 'driverGen'\n"
660 " software developer, and only in case of it's modification."
661 " Bus type (pci or\n vme) should be provided.\n\n");
663 /* show some examples examples */
664 printf("EXAMPLES: %s BNLDSP vme -gall\n"
665 " %s SHARED_CIBC vme\n\n",
669 #define OPT_COLLIDE(__opt) \
672 if (genOpt & (~__opt)) { \
673 genOpt = OPT_COLLIDE; \
679 #define MAX_NON_OPT_ARGS 3 /* max non-option arguments amount */
682 * @brief Parses command line arguments.
684 * @param argc -- command line argument count
685 * @param argv -- command line argument array
686 * @param md -- module description
690 static void ParseProgArgs(int argc
, char *argv
[], struct mdescr
*md
)
692 int cur_opt
; /* currently parsed option */
693 char arg_mas
[MAX_NON_OPT_ARGS
][NAME_LEN
]; /* hold all non-option
695 int arg_cntr
= 0; /* non-option arguments counter */
696 int expected_arg_amount
= 0;
698 memset(arg_mas
, 0, sizeof(arg_mas
));
700 getopt_long_only(argc
, argv
, "-hv", allLongOptions
,
701 NULL
)) != EOF
) && (genOpt
!= OPT_COLLIDE
)
702 && (glob_srv_arg
!= SRV_ARG_ERROR
) && (arg_cntr
!= 27051977)) {
704 case 1: /* this is non-option arg */
705 if (arg_cntr
== MAX_NON_OPT_ARGS
) {
709 strncpy(arg_mas
[arg_cntr
], optarg
, NAME_LEN
);
710 arg_mas
[arg_cntr
][NAME_LEN
- 1] = 0; /* safety
714 case 'h': /* user need help */
715 DisplayUsage(argv
[0]);
716 exit(EXIT_SUCCESS
); /* 0 */
718 case 'g': /* generate driver, controlled by git */
719 if (OPT_COLLIDE(OPT_G_IT
))
722 expected_arg_amount
= 2;
725 case 'a': /* generate full driver (include user part) */
726 if (OPT_COLLIDE(OPT_G_ALL
))
729 expected_arg_amount
= 2;
731 case 'i': /* only info file */
732 if (OPT_COLLIDE(OPT_G_INFO
))
735 expected_arg_amount
= 2;
737 case 'e': /* general part only (-general) */
738 if (OPT_COLLIDE(OPT_G_SHARED
))
740 genOpt
= OPT_G_SHARED
;
741 expected_arg_amount
= 0;
742 busType
= strdup(optarg
); /* set bus type */
743 driverName
= strdup("GENERAL"); /* set name for
746 case 's': /* we have service option */
747 /* see serviceOptions.h for more info */
748 if (OPT_COLLIDE(OPT_G_SERVICE
))
750 genOpt
= OPT_G_SERVICE
;
751 /* they've got non-option arguments. set their amount */
752 if (!strcmp(optarg
, "drvrvers")) {
753 expected_arg_amount
= 3;
754 glob_srv_arg
= SRV_VF_DRVR
; /* Verion File for
756 } else if (!strcmp(optarg
, "simvers")) {
757 expected_arg_amount
= 3;
758 glob_srv_arg
= SRV_VF_SIM
; /* Version File for
761 expected_arg_amount
= 0;
762 glob_srv_arg
= SRV_ARG_ERROR
;
765 case 'n': /* verbose printout during code generation */
768 case 'd': /* root directory, where driver directory will be created */
769 asprintf(&md
->mdn
, "%s", optarg
);
771 case 'v': /* version string */
772 printf("%s [Compiled on %s %s]\n", dg_version
,
776 case '?': /* wrong option */
778 fprintf(stderr
, "Wrong option.\n");
779 fprintf(stderr
, "Try \'%s -h\' for more information.\n",
781 exit(EXIT_FAILURE
); /* 1 */
786 if (genOpt
== OPT_COLLIDE
) { /* check for option colliding */
787 fprintf(stderr
, "Option collision detected!\n");
788 fprintf(stderr
, "Try \'%s -h\' for more information.\n",
790 exit(EXIT_FAILURE
); /* 1 */
793 if (!genOpt
) { /* user didn't provide command line
794 option -- set default */
795 genOpt
= OPT_G_IT
; /* by default create git-controlled driver */
796 expected_arg_amount
= 2;
799 if (glob_srv_arg
== SRV_ARG_ERROR
) { /* check service option argument */
800 fprintf(stderr
, "Wrong service option argument.\n");
801 fprintf(stderr
, "Try \'%s -h\' for more information.\n",
803 exit(EXIT_FAILURE
); /* 1 */
806 if (arg_cntr
!= expected_arg_amount
) { /* check for argument amount */
807 fprintf(stderr
, "Wrong arguments.\n");
808 fprintf(stderr
, "Try \'%s -h\' for more information.\n",
810 exit(EXIT_FAILURE
); /* 1 */
813 /* now we handle all non-option arguments
814 (they are in 'arg_mas' massive) */
819 driverName
= strdup(arg_mas
[0]); /* set DB driver name */
820 busType
= strdup(arg_mas
[1]); /* set bus type */
823 break; /* nothing to do */
825 switch (glob_srv_arg
) {
828 driverName
= strdup(arg_mas
[0]); /* set DB driver
830 busType
= strdup(arg_mas
[1]); /* set bus type */
831 SetSrvOptArgs(glob_srv_arg
, arg_mas
[2]);
840 if (!CheckBusType(busType
)) { /* check 'Bus Type' */
841 fprintf(stderr
, "Try \'%s -h\' for more information.\n",
843 exit(EXIT_FAILURE
); /* 1 */
847 asprintf(&md
->mdn
, "%s", DEFAULT_MASTER_DIR
);
851 * @brief Free allocated resources of module description.
853 * @param md -- module description.
856 static void free_md(struct mdescr
*md
)