1 /* HCHAN.C (c) Copyright Ivan Warren, 2005-2009 */
2 /* Generic channel device handler */
3
4 /* Based on work (c)Roger Bowler, Jan Jaeger & Others 1999-2009 */
5 /* This code is covered by the QPL Licence */
6 /**CAUTION*CAUTION*CAUTION*CAUTION*CAUTION*CAUTION*CAUTION*CAUTION****/
7 /* THIS CODE IS CURRENTLY IN A DEVELOPMENT STAGE AND IS NOT */
8 /* OPERATIONAL */
9 /* THIS FONCTIONALITY IS NOT YET SUPPORTED */
10 /**CAUTION*CAUTION*CAUTION*CAUTION*CAUTION*CAUTION*CAUTION*CAUTION****/
11
12 /*-------------------------------------------------------------------*/
13 /* This module contains code to handle a generic protocol to */
14 /* communicate with external device handlers. */
15 /*-------------------------------------------------------------------*/
16
17 #include "hstdinc.h"
18
19 #include "hercules.h"
20 #include "devtype.h"
21 #include "hchan.h"
22
23 #if defined(OPTION_DYNAMIC_LOAD) && defined(WIN32) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_)
24 SYSBLK *psysblk;
25 #define sysblk (*psysblk)
26 #endif
27
28 /*
29 * Initialisation string for a Generic Subchannel
30 *
31 * Format :
32 * <method> parms
33 * The 'EXEC' method will attempt to fork/exec the specified
34 * program. If the program dies during device initialisation, the
35 * subchannel will be invalidated (initialisation error). If it fails
36 * afterwards, the subchannel will be put offline and the offload
37 * thread will attempt to restart it at periodic intervals.
38 * The 'CONNECT' method will attempt to establish a TCP connection
39 * to the IP/PORT specified. If the connection fails, the connection
40 * will be attempted at periodic intervals.
41 * The 'ITHREAD' method will spawn a thread using a dynamically loaded module
42 */
hchan_init_handler(DEVBLK * dev,int argc,char * argv[])43 static int hchan_init_handler ( DEVBLK *dev, int argc, char *argv[] )
44 {
45 int rc;
46 dev->devtype=0x2880; /* Temporary until the device is actually initialised */
47 while(1)
48 {
49 if(argc<1)
50 {
51 logmsg("HHCGCH003E %4.4X : Missing Generic Channel method\n",dev->devnum);
52 rc=-1;
53 break;
54 }
55
56 if(strcasecmp(argv[0],"EXEC")==0)
57 {
58 rc=hchan_init_exec(dev,argc,argv);
59 break;
60 }
61 if(strcasecmp(argv[0],"CONNECT")==0)
62 {
63 rc=hchan_init_connect(dev,argc,argv);
64 break;
65 }
66 if(strcasecmp(argv[0],"ITHREAD")==0)
67 {
68 rc=hchan_init_int(dev,argc,argv);
69 break;
70 }
71 logmsg("HHCGCH001E %4.4X : Incorrect Generic Channel method %s\n",dev->devnum,argv[0]);
72 rc=-1;
73 break;
74 }
75 if(rc)
76 {
77 logmsg("HHCGCH002T %4.4X : Generic channel initialisation failed\n",dev->devnum);
78 }
79 logmsg("HHCGCH999W %4.4X : Generic channel is currently in development\n",dev->devnum);
80 return(rc);
81 }
82
hchan_init_exec(DEVBLK * dev,int ac,char ** av)83 static int hchan_init_exec(DEVBLK *dev,int ac,char **av)
84 {
85 UNREFERENCED(dev);
86 UNREFERENCED(ac);
87 UNREFERENCED(av);
88 return(0);
89 }
hchan_init_connect(DEVBLK * dev,int ac,char ** av)90 static int hchan_init_connect(DEVBLK *dev,int ac,char **av)
91 {
92 UNREFERENCED(dev);
93 UNREFERENCED(ac);
94 UNREFERENCED(av);
95 return(0);
96 }
hchan_init_int(DEVBLK * dev,int ac,char ** av)97 static int hchan_init_int(DEVBLK *dev,int ac,char **av)
98 {
99 UNREFERENCED(dev);
100 UNREFERENCED(ac);
101 UNREFERENCED(av);
102 return(0);
103 }
104
105 /*-------------------------------------------------------------------*/
106 /* Query the device definition */
107 /*-------------------------------------------------------------------*/
hchan_query_device(DEVBLK * dev,char ** class,int buflen,char * buffer)108 static void hchan_query_device (DEVBLK *dev, char **class,
109 int buflen, char *buffer)
110 {
111 BEGIN_DEVICE_CLASS_QUERY( "CHAN", dev, class, buflen, buffer );
112
113 snprintf(buffer,buflen,"** CONTROL UNIT OFFLINE **");
114 }
115
116 /*-------------------------------------------------------------------*/
117 /* Close the device */
118 /*-------------------------------------------------------------------*/
hchan_close_device(DEVBLK * dev)119 static int hchan_close_device ( DEVBLK *dev )
120 {
121 UNREFERENCED(dev);
122 return 0;
123 }
124
125
126 /*-------------------------------------------------------------------*/
127 /* Execute a Channel Command Word */
128 /*-------------------------------------------------------------------*/
hchan_execute_ccw(DEVBLK * dev,BYTE code,BYTE flags,BYTE chained,U16 count,BYTE prevcode,int ccwseq,BYTE * iobuf,BYTE * more,BYTE * unitstat,U16 * residual)129 static void hchan_execute_ccw ( DEVBLK *dev, BYTE code, BYTE flags,
130 BYTE chained, U16 count, BYTE prevcode, int ccwseq,
131 BYTE *iobuf, BYTE *more, BYTE *unitstat, U16 *residual )
132 {
133
134 UNREFERENCED(flags);
135 UNREFERENCED(prevcode);
136 UNREFERENCED(ccwseq);
137 UNREFERENCED(chained);
138 UNREFERENCED(count);
139 UNREFERENCED(iobuf);
140 UNREFERENCED(more);
141 UNREFERENCED(residual);
142
143 /* Process depending on CCW opcode */
144 switch (code) {
145 default:
146 /*---------------------------------------------------------------*/
147 /* INVALID OPERATION */
148 /*---------------------------------------------------------------*/
149 /* Set command reject sense byte, and unit check status */
150 dev->sense[0] = SENSE_CR;
151 *unitstat = CSW_CE | CSW_DE | CSW_UC;
152
153 }
154
155 }
156
157
158 #if defined(OPTION_DYNAMIC_LOAD)
159 static
160 #endif
161 DEVHND hchan_device_hndinfo = {
162 &hchan_init_handler, /* Device Initialisation */
163 &hchan_execute_ccw, /* Device CCW execute */
164 &hchan_close_device, /* Device Close */
165 &hchan_query_device, /* Device Query */
166 NULL, /* Device Start channel pgm */
167 NULL, /* Device End channel pgm */
168 NULL, /* Device Resume channel pgm */
169 NULL, /* Device Suspend channel pgm */
170 NULL, /* Device Read */
171 NULL, /* Device Write */
172 NULL, /* Device Query used */
173 NULL, /* Device Reserve */
174 NULL, /* Device Release */
175 NULL, /* Device Attention */
176 NULL, /* Immediate CCW Codes */
177 NULL, /* Signal Adapter Input */
178 NULL, /* Signal Adapter Output */
179 NULL, /* Hercules suspend */
180 NULL /* Hercules resume */
181 };
182
183 /* Libtool static name colision resolution */
184 /* note : lt_dlopen will look for symbol & modulename_LTX_symbol */
185 #if !defined(HDL_BUILD_SHARED) && defined(HDL_USE_LIBTOOL)
186 #define hdl_ddev hdt0000_LTX_hdl_ddev
187 #define hdl_depc hdt0000_LTX_hdl_depc
188 #define hdl_reso hdt0000_LTX_hdl_reso
189 #define hdl_init hdt0000_LTX_hdl_init
190 #define hdl_fini hdt0000_LTX_hdl_fini
191 #endif
192
193
194 #if defined(OPTION_DYNAMIC_LOAD)
195 HDL_DEPENDENCY_SECTION;
196 {
197 HDL_DEPENDENCY(HERCULES);
198 HDL_DEPENDENCY(DEVBLK);
199 HDL_DEPENDENCY(SYSBLK);
200 }
201 END_DEPENDENCY_SECTION
202
203
204 #if defined(WIN32) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_)
205 #undef sysblk
206 HDL_RESOLVER_SECTION;
207 {
208 HDL_RESOLVE_PTRVAR( psysblk, sysblk );
209 }
210 END_RESOLVER_SECTION
211 #endif
212
213
214 HDL_DEVICE_SECTION;
215 {
216 HDL_DEVICE(HCHAN, hchan_device_hndinfo );
217 HDL_DEVICE(2860, hchan_device_hndinfo );
218 HDL_DEVICE(2870, hchan_device_hndinfo );
219 HDL_DEVICE(2880, hchan_device_hndinfo );
220 HDL_DEVICE(9032, hchan_device_hndinfo );
221 }
222 END_DEVICE_SECTION
223 #endif
224