1 /* CONFIG.C (c) Copyright Jan Jaeger, 2000-2009 */
2 /* Device configuration functions */
3
4 /*-------------------------------------------------------------------*/
5 /* The original configuration builder is now called bldcfg.c */
6 /*-------------------------------------------------------------------*/
7
8 #include "hstdinc.h"
9
10 #define _CONFIG_C_
11 #define _HENGINE_DLL_
12
13 #include "hercules.h"
14 #include "opcode.h"
15
16 #if !defined(_GEN_ARCH)
17
18 #if defined(_ARCHMODE3)
19 #define _GEN_ARCH _ARCHMODE3
20 #include "config.c"
21 #undef _GEN_ARCH
22 #endif
23
24 #if defined(_ARCHMODE2)
25 #define _GEN_ARCH _ARCHMODE2
26 #include "config.c"
27 #undef _GEN_ARCH
28 #endif
29
30 #if defined(OPTION_FISHIO)
31 #include "w32chan.h"
32 #endif // defined(OPTION_FISHIO)
33
34
35 /*-------------------------------------------------------------------*/
36 /* Function to terminate all CPUs and devices */
37 /*-------------------------------------------------------------------*/
release_config()38 void release_config()
39 {
40 DEVBLK *dev;
41 int cpu;
42
43 /* Deconfigure all CPU's */
44 OBTAIN_INTLOCK(NULL);
45 for (cpu = 0; cpu < MAX_CPU_ENGINES; cpu++)
46 if(IS_CPU_ONLINE(cpu))
47 deconfigure_cpu(cpu);
48 RELEASE_INTLOCK(NULL);
49
50 #if defined(OPTION_SHARED_DEVICES)
51 /* Terminate the shared device listener thread */
52 if (sysblk.shrdtid)
53 signal_thread (sysblk.shrdtid, SIGUSR2);
54 #endif
55
56 /* Detach all devices */
57 for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev)
58 if (dev->allocated)
59 detach_subchan(SSID_TO_LCSS(dev->ssid), dev->subchan);
60
61 #if !defined(OPTION_FISHIO)
62 /* Terminate device threads */
63 obtain_lock (&sysblk.ioqlock);
64 sysblk.devtwait=0;
65 broadcast_condition (&sysblk.ioqcond);
66 release_lock (&sysblk.ioqlock);
67 #endif
68
69 } /* end function release_config */
70
71
72 /*-------------------------------------------------------------------*/
73 /* Function to start a new CPU thread */
74 /* Caller MUST own the intlock */
75 /*-------------------------------------------------------------------*/
configure_cpu(int cpu)76 int configure_cpu(int cpu)
77 {
78 int i;
79 char thread_name[16];
80
81 if(IS_CPU_ONLINE(cpu))
82 return -1;
83
84 snprintf(thread_name,sizeof(thread_name),"cpu%d thread",cpu);
85 thread_name[sizeof(thread_name)-1]=0;
86
87 if ( create_thread (&sysblk.cputid[cpu], DETACHED, cpu_thread,
88 &cpu, thread_name)
89 )
90 {
91 logmsg(_("HHCCF040E Cannot create CPU%4.4X thread: %s\n"),
92 cpu, strerror(errno));
93 return -1;
94 }
95
96 /* Find out if we are a cpu thread */
97 for (i = 0; i < MAX_CPU_ENGINES; i++)
98 if (sysblk.cputid[i] == thread_id())
99 break;
100
101 if (i < MAX_CPU_ENGINES)
102 sysblk.regs[i]->intwait = 1;
103
104 /* Wait for CPU thread to initialize */
105 wait_condition (&sysblk.cpucond, &sysblk.intlock);
106
107 if (i < MAX_CPU_ENGINES)
108 sysblk.regs[i]->intwait = 0;
109
110 return 0;
111 } /* end function configure_cpu */
112
113
114 /*-------------------------------------------------------------------*/
115 /* Function to remove a CPU from the configuration */
116 /* This routine MUST be called with the intlock held */
117 /*-------------------------------------------------------------------*/
deconfigure_cpu(int cpu)118 int deconfigure_cpu(int cpu)
119 {
120 int i;
121
122 /* Find out if we are a cpu thread */
123 for (i = 0; i < MAX_CPU_ENGINES; i++)
124 if (sysblk.cputid[i] == thread_id())
125 break;
126
127 /* If we're NOT trying to deconfigure ourselves */
128 if (cpu != i)
129 {
130 if (!IS_CPU_ONLINE(cpu))
131 return -1;
132
133 /* Deconfigure CPU */
134 sysblk.regs[cpu]->configured = 0;
135 sysblk.regs[cpu]->cpustate = CPUSTATE_STOPPING;
136 ON_IC_INTERRUPT(sysblk.regs[cpu]);
137
138 /* Wake up CPU as it may be waiting */
139 WAKEUP_CPU (sysblk.regs[cpu]);
140
141 /* (if we're a cpu thread) */
142 if (i < MAX_CPU_ENGINES)
143 sysblk.regs[i]->intwait = 1;
144
145 /* Wait for CPU thread to terminate */
146 wait_condition (&sysblk.cpucond, &sysblk.intlock);
147
148 /* (if we're a cpu thread) */
149 if (i < MAX_CPU_ENGINES)
150 sysblk.regs[i]->intwait = 0;
151
152 join_thread (sysblk.cputid[cpu], NULL);
153 detach_thread( sysblk.cputid[cpu] );
154 }
155 else
156 {
157 /* Else we ARE trying to deconfigure ourselves */
158 sysblk.regs[cpu]->configured = 0;
159 sysblk.regs[cpu]->cpustate = CPUSTATE_STOPPING;
160 ON_IC_INTERRUPT(sysblk.regs[cpu]);
161 }
162
163 sysblk.cputid[cpu] = 0;
164
165 return 0;
166
167 } /* end function deconfigure_cpu */
168
169
170 /* 4 next functions used for fast device lookup cache management */
171 #if defined(OPTION_FAST_DEVLOOKUP)
AddDevnumFastLookup(DEVBLK * dev,U16 lcss,U16 devnum)172 static void AddDevnumFastLookup(DEVBLK *dev,U16 lcss,U16 devnum)
173 {
174 unsigned int Channel;
175 if(sysblk.devnum_fl==NULL)
176 {
177 sysblk.devnum_fl=(DEVBLK ***)malloc(sizeof(DEVBLK **)*256*FEATURE_LCSS_MAX);
178 memset(sysblk.devnum_fl,0,sizeof(DEVBLK **)*256*FEATURE_LCSS_MAX);
179 }
180 Channel=(devnum & 0xff00)>>8 | ((lcss & (FEATURE_LCSS_MAX-1))<<8);
181 if(sysblk.devnum_fl[Channel]==NULL)
182 {
183 sysblk.devnum_fl[Channel]=(DEVBLK **)malloc(sizeof(DEVBLK *)*256);
184 memset(sysblk.devnum_fl[Channel],0,sizeof(DEVBLK *)*256);
185 }
186 sysblk.devnum_fl[Channel][devnum & 0xff]=dev;
187 }
188
189
AddSubchanFastLookup(DEVBLK * dev,U16 ssid,U16 subchan)190 static void AddSubchanFastLookup(DEVBLK *dev,U16 ssid, U16 subchan)
191 {
192 unsigned int schw;
193 #if 0
194 logmsg(D_("DEBUG : ASFL Adding %d\n"),subchan);
195 #endif
196 if(sysblk.subchan_fl==NULL)
197 {
198 sysblk.subchan_fl=(DEVBLK ***)malloc(sizeof(DEVBLK **)*256*FEATURE_LCSS_MAX);
199 memset(sysblk.subchan_fl,0,sizeof(DEVBLK **)*256*FEATURE_LCSS_MAX);
200 }
201 schw=((subchan & 0xff00)>>8)|(SSID_TO_LCSS(ssid)<<8);
202 if(sysblk.subchan_fl[schw]==NULL)
203 {
204 sysblk.subchan_fl[schw]=(DEVBLK **)malloc(sizeof(DEVBLK *)*256);
205 memset(sysblk.subchan_fl[schw],0,sizeof(DEVBLK *)*256);
206 }
207 sysblk.subchan_fl[schw][subchan & 0xff]=dev;
208 }
209
210
DelDevnumFastLookup(U16 lcss,U16 devnum)211 static void DelDevnumFastLookup(U16 lcss,U16 devnum)
212 {
213 unsigned int Channel;
214 if(sysblk.devnum_fl==NULL)
215 {
216 return;
217 }
218 Channel=(devnum & 0xff00)>>8 | ((lcss & (FEATURE_LCSS_MAX-1))<<8);
219 if(sysblk.devnum_fl[Channel]==NULL)
220 {
221 return;
222 }
223 sysblk.devnum_fl[Channel][devnum & 0xff]=NULL;
224 }
225
226
DelSubchanFastLookup(U16 ssid,U16 subchan)227 static void DelSubchanFastLookup(U16 ssid, U16 subchan)
228 {
229 unsigned int schw;
230 #if 0
231 logmsg(D_("DEBUG : DSFL Removing %d\n"),subchan);
232 #endif
233 if(sysblk.subchan_fl==NULL)
234 {
235 return;
236 }
237 schw=((subchan & 0xff00)>>8)|(SSID_TO_LCSS(ssid) << 8);
238 if(sysblk.subchan_fl[schw]==NULL)
239 {
240 return;
241 }
242 sysblk.subchan_fl[schw][subchan & 0xff]=NULL;
243 }
244 #endif
245
246
get_devblk(U16 lcss,U16 devnum)247 DEVBLK *get_devblk(U16 lcss, U16 devnum)
248 {
249 DEVBLK *dev;
250 DEVBLK**dvpp;
251
252 if(lcss >= FEATURE_LCSS_MAX)
253 lcss = 0;
254
255 for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev)
256 if (!(dev->allocated) && dev->ssid == LCSS_TO_SSID(lcss)) break;
257
258 if(!dev)
259 {
260 if (!(dev = (DEVBLK*)malloc(sizeof(DEVBLK))))
261 {
262 logmsg (_("HHCCF043E Cannot obtain device block\n"),
263 strerror(errno));
264 return NULL;
265 }
266 memset (dev, 0, sizeof(DEVBLK));
267
268 /* Initialize the device lock and conditions */
269 initialize_lock (&dev->lock);
270 initialize_condition (&dev->resumecond);
271 initialize_condition (&dev->iocond);
272 #if defined(OPTION_SCSI_TAPE)
273 initialize_condition (&dev->stape_sstat_cond);
274 InitializeListLink (&dev->stape_statrq.link);
275 InitializeListLink (&dev->stape_mntdrq.link);
276 dev->stape_statrq.dev = dev;
277 dev->stape_mntdrq.dev = dev;
278 dev->sstat = GMT_DR_OPEN(-1);
279 #endif
280
281 /* Search for the last device block on the chain */
282 for (dvpp = &(sysblk.firstdev); *dvpp != NULL;
283 dvpp = &((*dvpp)->nextdev));
284
285 /* Add the new device block to the end of the chain */
286 *dvpp = dev;
287
288 dev->ssid = LCSS_TO_SSID(lcss);
289 dev->subchan = sysblk.highsubchan[lcss]++;
290 }
291
292 /* Initialize the device block */
293 obtain_lock (&dev->lock);
294
295 dev->group = NULL;
296 dev->member = 0;
297
298 dev->cpuprio = sysblk.cpuprio;
299 dev->devprio = sysblk.devprio;
300 dev->hnd = NULL;
301 dev->devnum = devnum;
302 dev->chanset = lcss;
303 dev->fd = -1;
304 dev->syncio = 0;
305 dev->ioint.dev = dev;
306 dev->ioint.pending = 1;
307 dev->pciioint.dev = dev;
308 dev->pciioint.pcipending = 1;
309 dev->attnioint.dev = dev;
310 dev->attnioint.attnpending = 1;
311 dev->oslinux = sysblk.pgminttr == OS_LINUX;
312
313 /* Initialize storage view */
314 dev->mainstor = sysblk.mainstor;
315 dev->storkeys = sysblk.storkeys;
316 dev->mainlim = sysblk.mainsize - 1;
317
318 /* Initialize the path management control word */
319 memset (&dev->pmcw, 0, sizeof(PMCW));
320 dev->pmcw.devnum[0] = dev->devnum >> 8;
321 dev->pmcw.devnum[1] = dev->devnum & 0xFF;
322 dev->pmcw.lpm = 0x80;
323 dev->pmcw.pim = 0x80;
324 dev->pmcw.pom = 0xFF;
325 dev->pmcw.pam = 0x80;
326 dev->pmcw.chpid[0] = dev->devnum >> 8;
327
328 #if defined(OPTION_SHARED_DEVICES)
329 dev->shrdwait = -1;
330 #endif /*defined(OPTION_SHARED_DEVICES)*/
331
332 #ifdef _FEATURE_CHANNEL_SUBSYSTEM
333 /* Indicate a CRW is pending for this device */
334 #if defined(_370)
335 if (sysblk.arch_mode != ARCH_370)
336 #endif /*defined(_370)*/
337 dev->crwpending = 1;
338 #endif /*_FEATURE_CHANNEL_SUBSYSTEM*/
339
340 #ifdef EXTERNALGUI
341 if ( !dev->pGUIStat )
342 {
343 dev->pGUIStat = malloc( sizeof(GUISTAT) );
344 dev->pGUIStat->pszOldStatStr = dev->pGUIStat->szStatStrBuff1;
345 dev->pGUIStat->pszNewStatStr = dev->pGUIStat->szStatStrBuff2;
346 *dev->pGUIStat->pszOldStatStr = 0;
347 *dev->pGUIStat->pszNewStatStr = 0;
348 }
349 #endif /*EXTERNALGUI*/
350
351 /* Mark device valid */
352 dev->pmcw.flag5 |= PMCW5_V;
353 dev->allocated = 1;
354
355 return dev;
356 }
357
358
ret_devblk(DEVBLK * dev)359 void ret_devblk(DEVBLK *dev)
360 {
361 /* Mark device invalid */
362 dev->allocated = 0;
363 dev->pmcw.flag5 &= ~PMCW5_V; // compat ZZ deprecated
364 release_lock(&dev->lock);
365 }
366
367
368 /*-------------------------------------------------------------------*/
369 /* Function to build a device configuration block */
370 /*-------------------------------------------------------------------*/
attach_device(U16 lcss,U16 devnum,const char * type,int addargc,char * addargv[])371 int attach_device (U16 lcss, U16 devnum, const char *type,
372 int addargc, char *addargv[])
373 {
374 DEVBLK *dev; /* -> Device block */
375 int rc; /* Return code */
376 int i; /* Loop index */
377
378 /* Check whether device number has already been defined */
379 if (find_device_by_devnum(lcss,devnum) != NULL)
380 {
381 logmsg (_("HHCCF041E Device %d:%4.4X already exists\n"), lcss,devnum);
382 return 1;
383 }
384
385 /* obtain device block */
386 dev = get_devblk(lcss,devnum);
387
388 if(!(dev->hnd = hdl_ghnd(type)))
389 {
390 logmsg (_("HHCCF042E Device type %s not recognized\n"), type);
391
392 ret_devblk(dev);
393
394 return 1;
395 }
396
397 dev->typname = strdup(type);
398
399 /* Copy the arguments */
400 dev->argc = addargc;
401 if (addargc)
402 {
403 dev->argv = malloc ( addargc * sizeof(BYTE *) );
404 for (i = 0; i < addargc; i++)
405 if (addargv[i])
406 dev->argv[i] = strdup(addargv[i]);
407 else
408 dev->argv[i] = NULL;
409 }
410 else
411 dev->argv = NULL;
412
413 /* Call the device handler initialization function */
414 rc = (dev->hnd->init)(dev, addargc, addargv);
415
416 if (rc < 0)
417 {
418 logmsg (_("HHCCF044E Initialization failed for device %4.4X\n"),
419 devnum);
420
421 for (i = 0; i < dev->argc; i++)
422 if (dev->argv[i])
423 free(dev->argv[i]);
424 if (dev->argv)
425 free(dev->argv);
426
427 free(dev->typname);
428
429 ret_devblk(dev);
430
431 return 1;
432 }
433
434 /* Obtain device data buffer */
435 if (dev->bufsize != 0)
436 {
437 dev->buf = malloc (dev->bufsize);
438 if (dev->buf == NULL)
439 {
440 logmsg (_("HHCCF045E Cannot obtain buffer "
441 "for device %4.4X: %s\n"),
442 dev->devnum, strerror(errno));
443
444 for (i = 0; i < dev->argc; i++)
445 if (dev->argv[i])
446 free(dev->argv[i]);
447 if (dev->argv)
448 free(dev->argv);
449
450 free(dev->typname);
451
452 ret_devblk(dev);
453
454 return 1;
455 }
456 }
457
458 /* Release device lock */
459 release_lock(&dev->lock);
460
461 #ifdef _FEATURE_CHANNEL_SUBSYSTEM
462 /* Signal machine check */
463 #if defined(_370)
464 if (sysblk.arch_mode != ARCH_370)
465 #endif
466 machine_check_crwpend();
467 #endif /*_FEATURE_CHANNEL_SUBSYSTEM*/
468
469 /*
470 if(lcss!=0 && sysblk.arch_mode==ARCH_370)
471 {
472 logmsg(_("HHCCF078W %d:%4.4X : Only devices on CSS 0 are usable in S/370 mode\n"),lcss,devnum);
473 }
474 */
475
476 return 0;
477 } /* end function attach_device */
478
479
480 /*-------------------------------------------------------------------*/
481 /* Function to delete a device configuration block */
482 /*-------------------------------------------------------------------*/
detach_devblk(DEVBLK * dev)483 static int detach_devblk (DEVBLK *dev)
484 {
485 int i; /* Loop index */
486
487 /* Obtain the device lock */
488 obtain_lock(&dev->lock);
489
490 #if defined(OPTION_FAST_DEVLOOKUP)
491 DelSubchanFastLookup(dev->ssid, dev->subchan);
492 if(dev->pmcw.flag5 & PMCW5_V)
493 DelDevnumFastLookup(SSID_TO_LCSS(dev->ssid),dev->devnum);
494 #endif
495
496 /* Close file or socket */
497 if ((dev->fd > 2) || dev->console)
498 /* Call the device close handler */
499 (dev->hnd->close)(dev);
500
501 for (i = 0; i < dev->argc; i++)
502 if (dev->argv[i])
503 free(dev->argv[i]);
504 if (dev->argv)
505 free(dev->argv);
506
507 free(dev->typname);
508
509 #ifdef _FEATURE_CHANNEL_SUBSYSTEM
510 /* Indicate a CRW is pending for this device */
511 #if defined(_370)
512 if (sysblk.arch_mode != ARCH_370)
513 #endif /*defined(_370)*/
514 dev->crwpending = 1;
515 #endif /*_FEATURE_CHANNEL_SUBSYSTEM*/
516
517 // detach all devices in group
518 if(dev->group)
519 {
520 int i;
521
522 dev->group->memdev[dev->member] = NULL;
523
524 if(dev->group->members)
525 {
526 dev->group->members = 0;
527
528 for(i = 0; i < dev->group->acount; i++)
529 {
530 if(dev->group->memdev[i] && dev->group->memdev[i]->allocated)
531 {
532 detach_devblk(dev->group->memdev[i]);
533 }
534 }
535
536 free(dev->group);
537 }
538
539 dev->group = NULL;
540 }
541
542 ret_devblk(dev);
543
544 /* Zeroize the PMCW */
545 memset (&dev->pmcw, 0, sizeof(PMCW));
546
547 #ifdef _FEATURE_CHANNEL_SUBSYSTEM
548 /* Signal machine check */
549 #if defined(_370)
550 if (sysblk.arch_mode != ARCH_370)
551 #endif
552 machine_check_crwpend();
553 #endif /*_FEATURE_CHANNEL_SUBSYSTEM*/
554
555 return 0;
556 } /* end function detach_devblk */
557
558
559 /*-------------------------------------------------------------------*/
560 /* Function to delete a device configuration block by subchannel */
561 /*-------------------------------------------------------------------*/
detach_subchan(U16 lcss,U16 subchan)562 int detach_subchan (U16 lcss, U16 subchan)
563 {
564 DEVBLK *dev; /* -> Device block */
565 int rc;
566
567 /* Find the device block */
568 dev = find_device_by_subchan ((LCSS_TO_SSID(lcss)<<16)|subchan);
569
570 if (dev == NULL)
571 {
572 logmsg (_("HHCCF046E Subchannel %d:%4.4X does not exist\n"), lcss, subchan);
573 return 1;
574 }
575
576 rc = detach_devblk( dev );
577
578 if(!rc)
579 logmsg (_("HHCCF047I Subchannel %d:%4.4X detached\n"), lcss, subchan);
580
581 return rc;
582 }
583
584
585 /*-------------------------------------------------------------------*/
586 /* Function to delete a device configuration block by device number */
587 /*-------------------------------------------------------------------*/
detach_device(U16 lcss,U16 devnum)588 int detach_device (U16 lcss,U16 devnum)
589 {
590 DEVBLK *dev; /* -> Device block */
591 int rc;
592
593 /* Find the device block */
594 dev = find_device_by_devnum (lcss,devnum);
595
596 if (dev == NULL)
597 {
598 logmsg (_("HHCCF046E Device %d:%4.4X does not exist\n"), lcss, devnum);
599 return 1;
600 }
601
602 rc = detach_devblk( dev );
603
604 if(!rc)
605 logmsg (_("HHCCF047I Device %4.4X detached\n"), devnum);
606
607 return rc;
608 }
609
610
611 /*-------------------------------------------------------------------*/
612 /* Function to rename a device configuration block */
613 /*-------------------------------------------------------------------*/
define_device(U16 lcss,U16 olddevn,U16 newdevn)614 int define_device (U16 lcss, U16 olddevn,U16 newdevn)
615 {
616 DEVBLK *dev; /* -> Device block */
617
618 /* Find the device block */
619 dev = find_device_by_devnum (lcss, olddevn);
620
621 if (dev == NULL)
622 {
623 logmsg (_("HHCCF048E Device %d:%4.4X does not exist\n"), lcss, olddevn);
624 return 1;
625 }
626
627 /* Check that new device number does not already exist */
628 if (find_device_by_devnum(lcss, newdevn) != NULL)
629 {
630 logmsg (_("HHCCF049E Device %d:%4.4X already exists\n"), lcss, newdevn);
631 return 1;
632 }
633
634 /* Obtain the device lock */
635 obtain_lock(&dev->lock);
636
637 /* Update the device number in the DEVBLK */
638 dev->devnum = newdevn;
639
640 /* Update the device number in the PMCW */
641 dev->pmcw.devnum[0] = newdevn >> 8;
642 dev->pmcw.devnum[1] = newdevn & 0xFF;
643
644 /* Disable the device */
645 dev->pmcw.flag5 &= ~PMCW5_E;
646 #if defined(OPTION_FAST_DEVLOOKUP)
647 DelDevnumFastLookup(lcss,olddevn);
648 DelDevnumFastLookup(lcss,newdevn);
649 #endif
650
651 #ifdef _FEATURE_CHANNEL_SUBSYSTEM
652 /* Indicate a CRW is pending for this device */
653 #if defined(_370)
654 if (sysblk.arch_mode != ARCH_370)
655 #endif /*defined(_370)*/
656 dev->crwpending = 1;
657 #endif /*_FEATURE_CHANNEL_SUBSYSTEM*/
658
659 /* Release device lock */
660 release_lock(&dev->lock);
661
662 #ifdef _FEATURE_CHANNEL_SUBSYSTEM
663 /* Signal machine check */
664 #if defined(_370)
665 if (sysblk.arch_mode != ARCH_370)
666 #endif
667 machine_check_crwpend();
668 #endif /*_FEATURE_CHANNEL_SUBSYSTEM*/
669
670 // logmsg (_("HHCCF050I Device %4.4X defined as %4.4X\n"),
671 // olddevn, newdevn);
672
673 return 0;
674 } /* end function define_device */
675
676
677 /*-------------------------------------------------------------------*/
678 /* Function to group devblk's belonging to one device (eg OSA, LCS) */
679 /* */
680 /* group_device is intended to be called from within a device */
681 /* initialisation routine to group 1 or more devices to a logical */
682 /* device group. */
683 /* */
684 /* group_device will return true for the device that completes */
685 /* the device group. (ie the last device to join the group) */
686 /* */
687 /* when no group exists, and device group is called with a device */
688 /* count of zero, then no group will be created. Otherwise */
689 /* a new group will be created and the currently attaching device */
690 /* will be the first in the group. */
691 /* */
692 /* when a device in a group is detached, all devices in the group */
693 /* will be detached. The first device to be detached will enter */
694 /* its close routine with the group intact. Subsequent devices */
695 /* being detached will no longer have access to previously detached */
696 /* devices. */
697 /* */
698 /* Example of a fixed count device group: */
699 /* */
700 /* device_init(dev) */
701 /* { */
702 /* if( !device_group(dev, 2) ) */
703 /* return 0; */
704 /* */
705 /* ... all devices in the group have been attached, */
706 /* ... group initialisation may proceed. */
707 /* */
708 /* } */
709 /* */
710 /* */
711 /* Variable device group example: */
712 /* */
713 /* device_init(dev) */
714 /* { */
715 /* if( !group_device(dev, 0) && dev->group ) */
716 /* return 0; */
717 /* */
718 /* if( !device->group ) */
719 /* { */
720 /* ... process parameters to determine number of devices */
721 /* */
722 /* // Create group */
723 /* if( !group_device(dev, variable_count) ) */
724 /* return 0; */
725 /* } */
726 /* */
727 /* ... all devices in the group have been attached, */
728 /* ... group initialisation may proceed. */
729 /* } */
730 /* */
731 /* */
732 /* dev->group : pointer to DEVGRP structure or NULL */
733 /* dev->member : index into memdev array in DEVGRP structure for */
734 /* : current DEVBLK */
735 /* group->members : number of members in group */
736 /* group->acount : number active members in group */
737 /* group->memdev[] : array of DEVBLK pointers of member devices */
738 /* */
739 /* */
740 /* members will be equal to acount for a complete group */
741 /* */
742 /* */
743 /* Always: (for grouped devices) */
744 /* dev->group->memdev[dev->member] == dev */
745 /* */
746 /* */
747 /* Jan Jaeger, 23 Apr 2004 */
748 /*-------------------------------------------------------------------*/
group_device(DEVBLK * dev,int members)749 DLL_EXPORT int group_device(DEVBLK *dev, int members)
750 {
751 DEVBLK *tmp;
752
753 // Find a compatible group that is incomplete
754 for (tmp = sysblk.firstdev;
755 tmp != NULL
756 && (!tmp->allocated // not allocated
757 || !tmp->group // not a group device
758 || strcmp(tmp->typname,dev->typname) // unequal type
759 || (tmp->group->members == tmp->group->acount) ); // complete
760 tmp = tmp->nextdev) ;
761
762 if(tmp)
763 {
764 // Join Group
765 dev->group = tmp->group;
766 dev->member = dev->group->acount++;
767 dev->group->memdev[dev->member] = dev;
768 }
769 else if(members)
770 {
771 // Allocate a new Group when requested
772 dev->group = malloc(sizeof(DEVGRP) + members * sizeof(DEVBLK *));
773 dev->group->members = members;
774 dev->group->acount = 1;
775 dev->group->memdev[0] = dev;
776 dev->member = 0;
777 }
778
779 return (dev->group && (dev->group->members == dev->group->acount));
780 }
781
782
783 /*-------------------------------------------------------------------*/
784 /* Function to find a device block given the device number */
785 /*-------------------------------------------------------------------*/
find_device_by_devnum(U16 lcss,U16 devnum)786 DLL_EXPORT DEVBLK *find_device_by_devnum (U16 lcss,U16 devnum)
787 {
788 DEVBLK *dev;
789 #if defined(OPTION_FAST_DEVLOOKUP)
790 DEVBLK **devtab;
791 int Chan;
792
793 Chan=(devnum & 0xff00)>>8 | ((lcss & (FEATURE_LCSS_MAX-1))<<8);
794 if(sysblk.devnum_fl!=NULL)
795 {
796 devtab=sysblk.devnum_fl[Chan];
797 if(devtab!=NULL)
798 {
799 dev=devtab[devnum & 0xff];
800 if(dev && dev->allocated && dev->pmcw.flag5 & PMCW5_V && dev->devnum==devnum)
801 {
802 return dev;
803 }
804 else
805 {
806 DelDevnumFastLookup(lcss,devnum);
807 }
808 }
809 }
810
811 #endif
812 for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev)
813 if (dev->allocated && dev->devnum == devnum && lcss==SSID_TO_LCSS(dev->ssid) && dev->pmcw.flag5 & PMCW5_V) break;
814 #if defined(OPTION_FAST_DEVLOOKUP)
815 if(dev)
816 {
817 AddDevnumFastLookup(dev,lcss,devnum);
818 }
819 #endif
820 return dev;
821 } /* end function find_device_by_devnum */
822
823
824 /*-------------------------------------------------------------------*/
825 /* Function to find a device block given the subchannel number */
826 /*-------------------------------------------------------------------*/
find_device_by_subchan(U32 ioid)827 DEVBLK *find_device_by_subchan (U32 ioid)
828 {
829 U16 subchan = ioid & 0xFFFF;
830 DEVBLK *dev;
831 #if defined(OPTION_FAST_DEVLOOKUP)
832 unsigned int schw = ((subchan & 0xff00)>>8)|(IOID_TO_LCSS(ioid)<<8);
833 #if 0
834 logmsg(D_("DEBUG : FDBS FL Looking for %d\n"),subchan);
835 #endif
836 if(sysblk.subchan_fl && sysblk.subchan_fl[schw] && sysblk.subchan_fl[schw][subchan & 0xff])
837 return sysblk.subchan_fl[schw][subchan & 0xff];
838 #endif
839 #if 0
840 logmsg(D_("DEBUG : FDBS SL Looking for %8.8x\n"),ioid);
841 #endif
842 for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev)
843 if (dev->ssid == IOID_TO_SSID(ioid) && dev->subchan == subchan) break;
844
845 #if defined(OPTION_FAST_DEVLOOKUP)
846 if(dev)
847 {
848 AddSubchanFastLookup(dev, IOID_TO_SSID(ioid), subchan);
849 }
850 else
851 {
852 DelSubchanFastLookup(IOID_TO_SSID(ioid), subchan);
853 }
854 #endif
855
856 return dev;
857 } /* end function find_device_by_subchan */
858
859
860 /*-------------------------------------------------------------------*/
861 /* Returns a CPU register context for the device, or else NULL */
862 /*-------------------------------------------------------------------*/
devregs(DEVBLK * dev)863 REGS *devregs(DEVBLK *dev)
864 {
865 /* If a register context already exists then use it */
866 if (dev->regs)
867 return dev->regs;
868
869 /* Otherwise attempt to determine what it should be */
870 {
871 int i;
872 TID tid = thread_id(); /* Our own thread id */
873 for (i=0; i < MAX_CPU; i++)
874 if (tid == sysblk.cputid[i]) /* Are we a cpu thread? */
875 return sysblk.regs[i]; /* yes, use its context */
876 }
877 return NULL; /* Not CPU thread. Return NULL register context */
878 }
879
880
881 /*-------------------------------------------------------------------*/
882 /* Internal device parsing structures */
883 /*-------------------------------------------------------------------*/
884 typedef struct _DEVARRAY
885 {
886 U16 cuu1;
887 U16 cuu2;
888 } DEVARRAY;
889
890 typedef struct _DEVNUMSDESC
891 {
892 BYTE lcss;
893 DEVARRAY *da;
894 } DEVNUMSDESC;
895
896
897 /*-------------------------------------------------------------------*/
898 /* Function to Parse a LCSS specification in a device number spec */
899 /* Syntax : [lcss:]Anything... */
900 /* Function args : */
901 /* const char * spec : Parsed string */
902 /* char **rest : Rest of string (or original str) */
903 /* Returns : */
904 /* int : 0 if not specified, 0<=n<FEATURE_LCSS_MAX */
905 /* -1 Spec error */
906 /* */
907 /* If the function returns a positive value, then *rest should */
908 /* be freed by the caller. */
909 /*-------------------------------------------------------------------*/
910
911 static int
parse_lcss(const char * spec,char ** rest,int verbose)912 parse_lcss(const char *spec,
913 char **rest,int verbose)
914 {
915 int lcssid;
916 char *wrk;
917 char *lcss;
918 char *r;
919 char *strptr;
920 char *garbage;
921
922 wrk=malloc(strlen(spec)+1);
923 strcpy(wrk,spec);
924 lcss=strtok(wrk,":");
925 if(lcss==NULL)
926 {
927 if(verbose)
928 {
929 logmsg(_("HHCCF074E Unspecified error occured while parsing Logical Channel Subsystem Identification\n"));
930 }
931 free(wrk);
932 return(-1);
933 }
934 r=strtok(NULL,":");
935 if(r==NULL)
936 {
937 *rest=wrk;
938 return 0;
939 }
940 garbage=strtok(NULL,":");
941 if(garbage!=NULL)
942 {
943 if(verbose)
944 {
945 logmsg(_("HHCCF075E No more than 1 Logical Channel Subsystem Identification may be specified\n"));
946 }
947 free(wrk);
948 return(-1);
949 }
950 lcssid=strtoul(lcss,&strptr,10);
951 if(*strptr!=0)
952 {
953 if(verbose)
954 {
955 logmsg(_("HHCCF076E Non numeric Logical Channel Subsystem Identification %s\n"),lcss);
956 }
957 free(wrk);
958 return -1;
959 }
960 if(lcssid>FEATURE_LCSS_MAX)
961 {
962 if(verbose)
963 {
964 logmsg(_("HHCCF077E Logical Channel Subsystem Identification %d exceeds maximum of %d\n"),lcssid,FEATURE_LCSS_MAX-1);
965 }
966 free(wrk);
967 return -1;
968 }
969 *rest=malloc(strlen(r)+1);
970 strcpy(*rest,r);
971 free(wrk);
972 return lcssid;
973 }
974
975 static int
parse_single_devnum__INTERNAL(const char * spec,U16 * p_lcss,U16 * p_devnum,int verbose)976 parse_single_devnum__INTERNAL(const char *spec,
977 U16 *p_lcss,
978 U16 *p_devnum,
979 int verbose)
980 {
981 int rc;
982 U16 lcss;
983 char *r;
984 char *strptr;
985 rc=parse_lcss(spec,&r,verbose);
986 if(rc<0)
987 {
988 return -1;
989 }
990 lcss=rc;
991 rc=strtoul(r,&strptr,16);
992 if(rc<0 || rc>0xffff || *strptr!=0)
993 {
994 if(verbose)
995 {
996 logmsg(_("HHCCF055E Incorrect device address specification near character %c\n"),*strptr);
997 }
998 free(r);
999 return -1;
1000 }
1001 *p_devnum=rc;
1002 *p_lcss=lcss;
1003 return 0;
1004 }
1005
1006 DLL_EXPORT
1007 int
parse_single_devnum(const char * spec,U16 * lcss,U16 * devnum)1008 parse_single_devnum(const char *spec,
1009 U16 *lcss,
1010 U16 *devnum)
1011 {
1012 return parse_single_devnum__INTERNAL(spec,lcss,devnum,1);
1013 }
1014 int
parse_single_devnum_silent(const char * spec,U16 * lcss,U16 * devnum)1015 parse_single_devnum_silent(const char *spec,
1016 U16 *lcss,
1017 U16 *devnum)
1018 {
1019 return parse_single_devnum__INTERNAL(spec,lcss,devnum,0);
1020 }
1021
1022 /*-------------------------------------------------------------------*/
1023 /* Function to Parse compound device numbers */
1024 /* Syntax : [lcss:]CCUU[-CUU][,CUU..][.nn][...] */
1025 /* Examples : 200-23F */
1026 /* 200,201 */
1027 /* 200.16 */
1028 /* 200-23F,280.8 */
1029 /* etc... */
1030 /* : is the LCSS id separator (only 0 or 1 allowed and it must be 1st*/
1031 /* - is the range specification (from CUU to CUU) */
1032 /* , is the separator */
1033 /* . is the count indicator (nn is decimal) */
1034 /* 1st parm is the specification string as specified above */
1035 /* 2nd parm is the address of an array of DEVARRAY */
1036 /* Return value : 0 - Parsing error, etc.. */
1037 /* >0 - Size of da */
1038 /* */
1039 /* NOTE : A basic validity check is made for the following : */
1040 /* All CUUs must belong on the same channel */
1041 /* (this check is to eventually pave the way to a formal */
1042 /* channel/cu/device architecture) */
1043 /* no 2 identical CCUUs */
1044 /* ex : 200,300 : WRONG */
1045 /* 200.12,200.32 : WRONG */
1046 /* 2FF.2 : WRONG */
1047 /* NOTE : caller should free the array returned in da if the return */
1048 /* value is not 0 */
1049 /*-------------------------------------------------------------------*/
parse_devnums(const char * spec,DEVNUMSDESC * dd)1050 static size_t parse_devnums(const char *spec,DEVNUMSDESC *dd)
1051 {
1052 size_t gcount; /* Group count */
1053 size_t i; /* Index runner */
1054 char *grps; /* Pointer to current devnum group */
1055 char *sc; /* Specification string copy */
1056 DEVARRAY *dgrs; /* Device groups */
1057 U16 cuu1,cuu2; /* CUUs */
1058 char *strptr; /* strtoul ptr-ptr */
1059 int basechan=0; /* Channel for all CUUs */
1060 int duplicate; /* duplicated CUU indicator */
1061 int badcuu; /* offending CUU */
1062 int rc; /* Return code work var */
1063
1064 rc=parse_lcss(spec,&sc,1);
1065 if(rc<0)
1066 {
1067 return 0;
1068 }
1069 dd->lcss=rc;
1070
1071 /* Split by ',' groups */
1072 gcount=0;
1073 grps=strtok(sc,",");
1074 dgrs=NULL;
1075 while(grps!=NULL)
1076 {
1077 if(dgrs==NULL)
1078 {
1079 dgrs=malloc(sizeof(DEVARRAY));
1080 }
1081 else
1082 {
1083 dgrs=realloc(dgrs,(sizeof(DEVARRAY))*(gcount+1));
1084 }
1085 cuu1=strtoul(grps,&strptr,16);
1086 switch(*strptr)
1087 {
1088 case 0: /* Single CUU */
1089 cuu2=cuu1;
1090 break;
1091 case '-': /* CUU Range */
1092 cuu2=strtoul(&strptr[1],&strptr,16);
1093 if(*strptr!=0)
1094 {
1095 logmsg(_("HHCCF053E Incorrect second device number in device range near character %c\n"),*strptr);
1096 free(dgrs);
1097 free(sc);
1098 return(0);
1099 }
1100 break;
1101 case '.': /* CUU Count */
1102 cuu2=cuu1+strtoul(&strptr[1],&strptr,10);
1103 cuu2--;
1104 if(*strptr!=0)
1105 {
1106 logmsg(_("HHCCF054E Incorrect Device count near character %c\n"),*strptr);
1107 free(dgrs);
1108 free(sc);
1109 return(0);
1110 }
1111 break;
1112 default:
1113 logmsg(_("HHCCF055E Incorrect device address specification near character %c\n"),*strptr);
1114 free(dgrs);
1115 free(sc);
1116 return(0);
1117 }
1118 /* Check cuu1 <= cuu2 */
1119 if(cuu1>cuu2)
1120 {
1121 logmsg(_("HHCCF056E Incorrect device address range. %4.4X < %4.4X\n"),cuu2,cuu1);
1122 free(dgrs);
1123 free(sc);
1124 return(0);
1125 }
1126 if(gcount==0)
1127 {
1128 basechan=(cuu1 >> 8) & 0xff;
1129 }
1130 badcuu=-1;
1131 if(((cuu1 >> 8) & 0xff) != basechan)
1132 {
1133 badcuu=cuu1;
1134 }
1135 else
1136 {
1137 if(((cuu2 >> 8) & 0xff) != basechan)
1138 {
1139 badcuu=cuu2;
1140 }
1141 }
1142 if(badcuu>=0)
1143 {
1144 logmsg(_("HHCCF057E %4.4X is on wrong channel (1st device defined on channel %2.2X)\n"),badcuu,basechan);
1145 free(dgrs);
1146 free(sc);
1147 return(0);
1148 }
1149 /* Check for duplicates */
1150 duplicate=0;
1151 for(i=0;i<gcount;i++)
1152 {
1153 /* check 1st cuu not within existing range */
1154 if(cuu1>=dgrs[i].cuu1 && cuu1<=dgrs[i].cuu2)
1155 {
1156 duplicate=1;
1157 break;
1158 }
1159 /* check 2nd cuu not within existing range */
1160 if(cuu2>=dgrs[i].cuu1 && cuu1<=dgrs[i].cuu2)
1161 {
1162 duplicate=1;
1163 break;
1164 }
1165 /* check current range doesn't completelly overlap existing range */
1166 if(cuu1<dgrs[i].cuu1 && cuu2>dgrs[i].cuu2)
1167 {
1168 duplicate=1;
1169 break;
1170 }
1171 }
1172 if(duplicate)
1173 {
1174 logmsg(_("HHCCF058E Some or all devices in %4.4X-%4.4X duplicate devices already defined\n"),cuu1,cuu2);
1175 free(dgrs);
1176 free(sc);
1177 return(0);
1178 }
1179 dgrs[gcount].cuu1=cuu1;
1180 dgrs[gcount].cuu2=cuu2;
1181 gcount++;
1182 grps=strtok(NULL,",");
1183 }
1184 free(sc);
1185 dd->da=dgrs;
1186 return(gcount);
1187 }
1188
1189 int
parse_and_attach_devices(const char * sdevnum,const char * sdevtype,int addargc,char ** addargv)1190 parse_and_attach_devices(const char *sdevnum,
1191 const char *sdevtype,
1192 int addargc,
1193 char **addargv)
1194 {
1195 DEVNUMSDESC dnd;
1196 int baddev;
1197 size_t devncount;
1198 DEVARRAY *da;
1199 int i;
1200 U16 devnum;
1201 int rc;
1202
1203 #if defined(OPTION_CONFIG_SYMBOLS)
1204 int j;
1205 char **newargv;
1206 char **orig_newargv;
1207 #endif
1208
1209 devncount=parse_devnums(sdevnum,&dnd);
1210
1211 if(devncount==0)
1212 {
1213 return -2;
1214 }
1215
1216 #if defined(OPTION_CONFIG_SYMBOLS)
1217 newargv=malloc(MAX_ARGS*sizeof(char *));
1218 orig_newargv=malloc(MAX_ARGS*sizeof(char *));
1219 #endif /* #if defined(OPTION_CONFIG_SYMBOLS) */
1220 for(baddev=0,i=0;i<(int)devncount;i++)
1221 {
1222 da=dnd.da;
1223 for(devnum=da[i].cuu1;devnum<=da[i].cuu2;devnum++)
1224 {
1225 #if defined(OPTION_CONFIG_SYMBOLS)
1226 char wrkbfr[16];
1227 snprintf(wrkbfr,sizeof(wrkbfr),"%3.3x",devnum);
1228 set_symbol("cuu",wrkbfr);
1229 snprintf(wrkbfr,sizeof(wrkbfr),"%4.4x",devnum);
1230 set_symbol("ccuu",wrkbfr);
1231 snprintf(wrkbfr,sizeof(wrkbfr),"%3.3X",devnum);
1232 set_symbol("CUU",wrkbfr);
1233 snprintf(wrkbfr,sizeof(wrkbfr),"%4.4X",devnum);
1234 set_symbol("CCUU",wrkbfr);
1235 snprintf(wrkbfr,sizeof(wrkbfr),"%d",dnd.lcss);
1236 set_symbol("CSS",wrkbfr);
1237 for(j=0;j<addargc;j++)
1238 {
1239 orig_newargv[j]=newargv[j]=resolve_symbol_string(addargv[j]);
1240 }
1241 /* Build the device configuration block */
1242 rc=attach_device(dnd.lcss, devnum, sdevtype, addargc, newargv);
1243 for(j=0;j<addargc;j++)
1244 {
1245 free(orig_newargv[j]);
1246 }
1247 #else /* #if defined(OPTION_CONFIG_SYMBOLS) */
1248 /* Build the device configuration block (no syms) */
1249 rc=attach_device(dnd.lcss, devnum, sdevtype, addargc, addargv);
1250 #endif /* #if defined(OPTION_CONFIG_SYMBOLS) */
1251 if(rc!=0)
1252 {
1253 baddev=1;
1254 break;
1255 }
1256 }
1257 if(baddev)
1258 {
1259 break;
1260 }
1261 }
1262 #if defined(OPTION_CONFIG_SYMBOLS)
1263 free(newargv);
1264 free(orig_newargv);
1265 #endif /* #if defined(OPTION_CONFIG_SYMBOLS) */
1266 free(dnd.da);
1267 return baddev?0:-1;
1268 }
1269
1270 #define MAX_LOGO_LINES 256
1271 void
clearlogo()1272 clearlogo()
1273 {
1274 size_t i;
1275 if(sysblk.herclogo!=NULL)
1276 {
1277 for(i=0;i<sysblk.logolines;i++)
1278 {
1279 free(sysblk.herclogo[i]);
1280 }
1281 free(sysblk.herclogo);
1282 sysblk.herclogo=NULL;
1283 }
1284 }
1285 int
readlogo(char * fn)1286 readlogo(char *fn)
1287 {
1288 char **data;
1289 char bfr[256];
1290 char *rec;
1291 FILE *lf;
1292
1293 clearlogo();
1294
1295 lf=fopen(fn,"r");
1296 if(lf==NULL)
1297 {
1298 return -1;
1299 }
1300 data=malloc(sizeof(char *)*MAX_LOGO_LINES);
1301 sysblk.logolines=0;
1302 while((rec=fgets(bfr,sizeof(bfr),lf))!=NULL)
1303 {
1304 rec[strlen(rec)-1]=0;
1305 data[sysblk.logolines]=malloc(strlen(rec)+1);
1306 strcpy(data[sysblk.logolines],rec);
1307 sysblk.logolines++;
1308 if(sysblk.logolines>MAX_LOGO_LINES)
1309 {
1310 break;
1311 }
1312 }
1313 fclose(lf);
1314 sysblk.herclogo=data;
1315 return 0;
1316 }
1317
parse_conkpalv(char * s,int * idle,int * intv,int * cnt)1318 DLL_EXPORT int parse_conkpalv(char* s, int* idle, int* intv, int* cnt )
1319 {
1320 size_t n; char *p1, *p2, *p3, c;
1321 ASSERT(s && *s && idle && intv && cnt);
1322 if (!s || !*s || !idle || !intv || !cnt) return -1;
1323 // Format: "(idle,intv,cnt)". All numbers. No spaces.
1324 if (0
1325 || (n = strlen(s)) < 7
1326 || s[0] != '('
1327 || s[n-1] != ')'
1328 )
1329 return -1;
1330 // 1st sub-operand
1331 if (!(p1 = strchr(s+1, ','))) return -1;
1332 c = *p1; *p1 = 0;
1333 if ( strspn( s+1, "0123456789" ) != strlen(s+1) )
1334 {
1335 *p1 = c;
1336 return -1;
1337 }
1338 *p1 = c;
1339 // 2nd sub-operand
1340 if (!(p2 = strchr(p1+1, ','))) return -1;
1341 c = *p2; *p2 = 0;
1342 if ( strspn( p1+1, "0123456789" ) != strlen(p1+1) )
1343 {
1344 *p2 = c;
1345 return -1;
1346 }
1347 *p2 = c;
1348 // 3rd sub-operand
1349 if (!(p3 = strchr(p2+1, ')'))) return -1;
1350 c = *p3; *p3 = 0;
1351 if ( strspn( p2+1, "0123456789" ) != strlen(p2+1) )
1352 {
1353 *p3 = c;
1354 return -1;
1355 }
1356 *p3 = c;
1357 // convert each to number
1358 c = *p1; *p1 = 0; *idle = atoi(s+1); *p1 = c;
1359 c = *p2; *p2 = 0; *intv = atoi(p1+1); *p2 = c;
1360 c = *p3; *p3 = 0; *cnt = atoi(p2+1); *p3 = c;
1361 // check results
1362 if (*idle <= 0 || INT_MAX == *idle) return -1;
1363 if (*intv <= 0 || INT_MAX == *intv) return -1;
1364 if (*cnt <= 0 || INT_MAX == *cnt ) return -1;
1365 return 0;
1366 }
1367
1368 #endif /*!defined(_GEN_ARCH)*/
1369