1 /* CTCADPT.C (c) Copyright James A. Pierson, 2002-2012 */
2 /* (c) Copyright Roger Bowler, 2000-2012 */
3 /* (c) Copyright Willem Konynenberg, 2000-2009 */
4 /* (c) Copyright Vic Cross, 2001-2009 */
5 /* Hercules Channel-to-Channel Emulation Support */
6
7 // vmnet (C) Copyright Willem Konynenberg, 2000-2009
8 // CTCT (C) Copyright Vic Cross, 2001-2009
9 // CTCE (C) Copyright Peter J. Jansen, 2014-2016
10
11 // Notes:
12 // This module contains the remaining CTC emulation modes that
13 // have not been moved to seperate modules. There is also logic
14 // to allow old style 3088 device definitions for compatibility
15 // and may be removed in a future release.
16 //
17 // Please read README.NETWORKING for more info.
18 //
19
20 #include "hstdinc.h"
21
22 #define _CTCADPT_C_
23 #define _HENGINE_DLL_
24
25 #include "hercules.h"
26 #include "devtype.h"
27 #include "ctcadpt.h"
28
29 #include "opcode.h"
30 #include "devtype.h"
31
32 // --------------------------------------------------------------------
33 // CTCE Info also for use by CTCE Tracing when requested
34 // --------------------------------------------------------------------
35
36 typedef struct _CTCE_INFO
37 {
38 BYTE state_x_prev; /* This side previous state */
39 BYTE state_y_prev; /* Other side previous state */
40 BYTE actions; /* Triggered by CCW received */
41 BYTE state_new; /* The updated FSM state */
42 BYTE x_unit_stat; /* Resulting device unit stat */
43 BYTE scb; /* Last SCB returned */
44 BYTE busy_waits; /* Number of times waited for */
45 /* a Busy condition to end */
46 BYTE de_ready; /* Device-End status */
47 /* indicating ready to be */
48 /* presented, yielding ... */
49 u_int sent : 1; /* = 1 : CTCE_Send done */
50 u_int attn_can : 1; /* = 1 : Atttention Cancelled */
51 u_int con_lost : 1; /* = 1 : contention lost */
52 u_int con_won : 1; /* = 1 : contention won */
53 int wait_rc; /* CTCE_Send Wait RC if used */
54 int de_ready_attn_rc; /* device_attention RC */
55 int working_attn_rc; /* device_attention RC */
56 /* from transition to */
57 /* "Working(D)" state */
58 int sok_buf_len; /* socket buffer length */
59 }
60 CTCE_INFO;
61
62 // --------------------------------------------------------------------
63 // CTCE_Cmd_Xfr enumeration type used by CTCE_Trace
64 // --------------------------------------------------------------------
65
66 enum CTCE_Cmd_Xfr
67 {
68 CTCE_LCL, /* Cmd remains Local only */
69 CTCE_SND, /* Cmd Send to y-side */
70 CTCE_RCV /* Cmd Received from y-side */
71 };
72
73 // ====================================================================
74 // Declarations
75 // ====================================================================
76
77 static int CTCT_Init( DEVBLK *dev, int argc, char *argv[] );
78
79 static void CTCT_Read( DEVBLK* pDEVBLK, U16 sCount,
80 BYTE* pIOBuf, BYTE* pUnitStat,
81 U16* pResidual, BYTE* pMore );
82
83 static void CTCT_Write( DEVBLK* pDEVBLK, U16 sCount,
84 BYTE* pIOBuf, BYTE* pUnitStat,
85 U16* pResidual );
86
87 static void* CTCT_ListenThread( void* argp );
88
89 static void CTCE_ExecuteCCW( DEVBLK* pDEVBLK, BYTE bCode,
90 BYTE bFlags, BYTE bChained,
91 U16 sCount, BYTE bPrevCode,
92 int iCCWSeq, BYTE* pIOBuf,
93 BYTE* pMore, BYTE* pUnitStat,
94 U16* pResidual );
95
96 static int CTCE_Init( DEVBLK *dev, int argc, char *argv[] );
97
98 static void CTCE_Send( DEVBLK* pDEVBLK, U16 sCount,
99 BYTE* pIOBuf, BYTE* pUnitStat,
100 U16* pResidual, CTCE_INFO* pCTCE_Info );
101
102 static void* CTCE_RecvThread( void* argp );
103
104 static void* CTCE_ListenThread( void* argp );
105
106 static void CTCE_Halt( DEVBLK* pDEVBLK );
107
108 static U32 CTCE_ChkSum( const BYTE* pBuf, const U16 BufLen );
109
110 static void CTCE_Trace( const DEVBLK* pDEVBLK,
111 const U16 sCount,
112 const enum CTCE_Cmd_Xfr eCTCE_Cmd_Xfr,
113 const CTCE_INFO* pCTCE_Info,
114 const BYTE* pCTCE_Buf,
115 const BYTE* pUnitStat );
116
117 static int CTCE_Connect_Timeout( int sockfd,
118 const struct sockaddr* saptr,
119 const socklen_t salen,
120 const int usec );
121
122 static int VMNET_Init( DEVBLK *dev, int argc, char *argv[] );
123
124 static int VMNET_Write( DEVBLK *dev, BYTE *iobuf,
125 U16 count, BYTE *unitstat );
126
127 static int VMNET_Read( DEVBLK *dev, BYTE *iobuf,
128 U16 count, BYTE *unitstat );
129
130 // --------------------------------------------------------------------
131 // Definitions for CTC general data blocks
132 // --------------------------------------------------------------------
133
134 typedef struct _CTCG_PARMBLK
135 {
136 int listenfd;
137 struct sockaddr_in addr;
138 DEVBLK* dev;
139 }
140 CTCG_PARMBLK;
141
142 // --------------------------------------------------------------------
143 // CTCE Send-Receive Socket Prefix at the start of the DEVBLK buf
144 // --------------------------------------------------------------------
145
146 typedef struct _CTCE_SOKPFX
147 {
148 BYTE CmdReg; /* CTCE command register */
149 BYTE FsmSta; /* CTCE FSM state */
150 U16 sCount; /* CTCE sCount copy */
151 U16 PktSeq; /* CTCE Packet Sequence ID */
152 U16 SndLen; /* CTCE Packet Sent Length */
153 U16 DevNum; /* CTCE Sender's devnum */
154 U16 ssid; /* CTCE Sender's ssid */
155 }
156 CTCE_SOKPFX;
157
158 // --------------------------------------------------------------------
159 // CTCE Equivalent of CTCG_PARMBLK
160 // --------------------------------------------------------------------
161
162 typedef struct _CTCE_PARMBLK
163 {
164 int listenfd[2]; /* [0] = read, [1] = write */
165 struct sockaddr_in addr;
166 DEVBLK* dev;
167 }
168 CTCE_PARMBLK;
169
170 // --------------------------------------------------------------------
171 // CTCE Constants (generated by a small REXX script)
172 // --------------------------------------------------------------------
173
174 #define CTCE_PREPARE 0
175 #define CTCE_CONTROL 1
176 #define CTCE_READ 2
177 #define CTCE_WRITE 3
178 #define CTCE_SENSE_COMMAND_BYTE 4
179 #define CTCE_READ_BACKWARD 6
180 #define CTCE_WRITE_END_OF_FILE 7
181 #define CTCE_NO_OPERATION 8
182 #define CTCE_SET_EXTENDED_MODE 9
183 #define CTCE_SENSE_ADAPTER_STATE 10
184 #define CTCE_SENSE_ID 11
185 #define CTCE_READ_CONFIG_DATA 12
186 #define CTCE_SET_BASIC_MODE 15
187
188 static char *CTCE_CmdStr[16] = {
189 "PRE" , // 0 = 00 = Prepare
190 "CTL" , // 1 = 01 = Control
191 "RED" , // 2 = 02 = Read
192 "WRT" , // 3 = 03 = Write
193 "SCB" , // 4 = 04 = Sense Command Byte
194 "???" , // 5 = 05 = Not Used
195 "RBK" , // 6 = 06 = Read Backward
196 "WEF" , // 7 = 07 = Write End Of File
197 "NOP" , // 8 = 10 = No Operation
198 "SEM" , // 9 = 11 = Set Extended Mode
199 "SAS" , // 10 = 12 = Sense Adapter State
200 "SID" , // 11 = 13 = Sense ID
201 "RCD" , // 12 = 14 = Read Configuration Data
202 "???" , // 13 = 15 = Invalid Command Code
203 "CB0" , // 14 = 16 = Invalid Command Code Used to Report SCB 0
204 "SBM" // 15 = 17 = Set Basic Mode
205 };
206
207 static BYTE CTCE_command[256] = {
208 14, 3, 2, 8,10, 3, 2, 1,13, 3, 2, 8, 6, 3, 2, 1,
209 13, 3, 2, 8, 4, 3, 2, 1,13, 3, 2, 8, 6, 3, 2, 1,
210 13, 3, 2, 8,13, 3, 2, 1,13, 3, 2, 8, 6, 3, 2, 1,
211 13, 3, 2, 8, 4, 3, 2, 1,13, 3, 2, 8, 6, 3, 2, 1,
212 13, 3, 2,15,13, 3, 2, 1,13, 3, 2,15, 6, 3, 2, 1,
213 13, 3, 2,15, 4, 3, 2, 1,13, 3, 2,15, 6, 3, 2, 1,
214 13, 3, 2,15,13, 3, 2, 1,13, 3, 2,15, 6, 3, 2, 1,
215 13, 3, 2,15, 4, 3, 2, 1,13, 3, 2,15, 6, 3, 2, 1,
216 13, 7, 2, 8,13, 7, 2, 1,13, 7, 2, 8, 6, 7, 2, 1,
217 13, 7, 2, 8, 4, 7, 2, 1,13, 7, 2, 8, 6, 7, 2, 1,
218 13, 7, 2, 8,13, 7, 2, 1,13, 7, 2, 8, 6, 7, 2, 1,
219 13, 7, 2, 8, 4, 7, 2, 1,13, 7, 2, 8, 6, 7, 2, 1,
220 13, 7, 2, 9,13, 7, 2, 1,13, 7, 2,13, 6, 7, 2, 1,
221 13, 7, 2,13, 4, 7, 2, 1,13, 7, 2,13, 6, 7, 2, 1,
222 13, 7, 2, 0,11, 7, 2, 1,13, 7, 2,13, 6, 7, 2, 1,
223 13, 7, 2,13, 4, 7, 2, 1,13, 7, 2,13, 6, 7, 2, 1
224 };
225
226 /* In base (non-extended) mode the WEOF (WEF) */
227 /* command does not exist but classifies as */
228 /* a regular WRITE command. The WEOF-to-WRT */
229 /* mapping is performed with this macro: */
230 #define CTCE_CMD(c) (pDEVBLK->ctcxmode == 1 ? (CTCE_command[c]) : \
231 ((CTCE_command[c])==7 ? 3 : (CTCE_command[c])))
232
233 #define IS_CTCE_CCW_PRE(c) ((CTCE_command[c]==0))
234 #define IS_CTCE_CCW_CTL(c) ((CTCE_command[c]==1))
235 #define IS_CTCE_CCW_RED(c) ((CTCE_command[c]==2))
236 #define IS_CTCE_CCW_WRT(c) ((CTCE_CMD( c) ==3))
237 #define IS_CTCE_CCW_SCB(c) ((CTCE_command[c]==4))
238 #define IS_CTCE_CCW_RBK(c) ((CTCE_command[c]==6))
239 #define IS_CTCE_CCW_WEF(c) ((CTCE_CMD( c )==7))
240 #define IS_CTCE_CCW_NOP(c) ((CTCE_command[c]==8))
241 #define IS_CTCE_CCW_SEM(c) ((CTCE_command[c]==9))
242 #define IS_CTCE_CCW_SBM(c) ((CTCE_command[c]==15))
243 #define IS_CTCE_CCW_SAS(c) ((CTCE_command[c]==10))
244 #define IS_CTCE_CCW_SID(c) ((CTCE_command[c]==11))
245 #define IS_CTCE_CCW_RCD(c) ((CTCE_command[c]==12))
246 #define IS_CTCE_CCW_DEP(c) ((CTCE_CMD( c )<7)) /* Any Dependent Command */
247 #define IS_CTCE_CCW_RDA(c) (((CTCE_command[c]&0xFB)==2)) /* Read or Read Backward */
248 #define IS_CTCE_CCW_WRA(c) (((CTCE_command[c]&0xFB)==3)) /* Write or Write EOF */
249
250 /* Macros for classifying CTC states follow. */
251 /* These are numbered 0 thru 7 as per the */
252 /* column numbers 0-3 and 4-7 in the table */
253 /* in section 2.13 in SA22-7203-00 by IBM, */
254 /* which is (alomost) the same as the table */
255 /* in section 3.15 in SA22-7901-01 by IBM. */
256 /* */
257 /* But in base (non-extended) mode, the table */
258 /* in section 2.13 in SA77-7901-01 applies, */
259 /* omitting column 5 for the Not-Ready state: */
260 /* base (non-extended) mode considers this */
261 /* the same as Available. We perform this */
262 /* Base-Not-Ready mapping into Available with */
263 /* this macro: */
264 #define CTCE_STATE(c) (pDEVBLK->ctcxmode == 1 ? ((c)&0x07) : \
265 (((c)&0x07)==0x05 ? 0x04 : ((c)&0x07)))
266
267 #define IS_CTCE_YWP(c) (((c)&0x07)==0x00)
268 #define IS_CTCE_YWC(c) (((c)&0x07)==0x01)
269 #define IS_CTCE_YWR(c) (((c)&0x07)==0x02)
270 #define IS_CTCE_YWW(c) (((c)&0x07)==0x03)
271 #define IS_CTCE_YAV(c) ((CTCE_STATE(c))==0x04)
272 #define IS_CTCE_YNR(c) ((CTCE_STATE(c))==0x05)
273 #define IS_CTCE_XWK(c) (((c)&0x07)==0x06)
274 #define IS_CTCE_XIP(c) (((c)&0x07)==0x07)
275
276 /* These two are useful combinations : */
277 /* - The 0 (YWP) or 4 (YAV) states READY */
278 #define IS_CTCE_YAP(c) (((CTCE_STATE(c))&0x03)==0x00)
279 /* - Any Y working state: YWP, YWC, YWR or YWW */
280 #define IS_CTCE_YWK(c) (((c)&0x04)==0x00)
281 /* - Any of the states Cntl, Read, or Write */
282 #define IS_CTCE_CRW(c) ((((c)&0x04)==0x00) && (((c)&0x07)!=0x00))
283
284 /* A special one is "X available" (XAV) which */
285 /* includes the not ready state. */
286 #define IS_CTCE_XAV(c) (((c)<6))
287
288 /* And the corresponding SET macros for these */
289 /* The first four, i.e. a SET to any YWK, */
290 /* includes the setting of the CTCE_WAIT bit. */
291 #define SET_CTCE_YWP(c) (c=(((c)&0xF8)|0x00))
292 #define SET_CTCE_YWC(c) (c=(((c)&0xF8)|0x01))
293 #define SET_CTCE_YWR(c) (c=(((c)&0xF8)|0x02))
294 #define SET_CTCE_YWW(c) (c=(((c)&0xF8)|0x03))
295 #define SET_CTCE_YAV(c) (c=(((c)&0xF8)|0x04))
296 #define SET_CTCE_YNR(c) (c=(((c)&0xF8)|0x05))
297 #define SET_CTCE_XWK(c) (c=(((c)&0xF8)|0x06))
298 #define SET_CTCE_XIP(c) (c=((c)|0x07))
299
300 /* One letter CTC state abbreviations */
301 static char *CTCE_StaStr[8] = {"P", "C", "R", "W", "A", "N", "X", "I"};
302
303 /* The CTCE CCW command will trigger actions */
304 /* which are dependent on the CTCE state. */
305 /* These different action flags are : */
306 #define CTCE_WEOF (0x80)
307 #define CTCE_SEND (0x40)
308 #define CTCE_WAIT (0x20)
309 #define CTCE_ATTN (0x10)
310 #define CTCE_MATCH (0x08)
311
312 /* Corresponding macros to test for these */
313 #define IS_CTCE_WEOF(c) (((c)&CTCE_WEOF)==CTCE_WEOF)
314 #define IS_CTCE_SEND(c) (((c)&CTCE_SEND)==CTCE_SEND)
315 #define IS_CTCE_WAIT(c) (((c)&CTCE_WAIT)==CTCE_WAIT)
316 #define IS_CTCE_ATTN(c) (((c)&CTCE_ATTN)==CTCE_ATTN)
317 #define IS_CTCE_MATCH(c) (((c)&CTCE_MATCH)==CTCE_MATCH)
318
319 /* And the corresponding SET macros for these */
320 #define SET_CTCE_WEOF(c) (c|=CTCE_WEOF)
321 #define SET_CTCE_SEND(c) (c|=CTCE_SEND)
322 #define SET_CTCE_WAIT(c) (c|=CTCE_WAIT)
323 #define SET_CTCE_ATTN(c) (c|=CTCE_ATTN)
324 #define SET_CTCE_MATCH(c) (c|=CTCE_MATCH)
325
326 /* And the corresponding CLeaR macros */
327 #define CLR_CTCE_WEOF(c) (c&=~CTCE_WEOF)
328 #define CLR_CTCE_SEND(c) (c&=~CTCE_SEND)
329 #define CLR_CTCE_WAIT(c) (c&=~CTCE_WAIT)
330 #define CLR_CTCE_ATTN(c) (c&=~CTCE_ATTN)
331 #define CLR_CTCE_MATCH(c) (c&=~CTCE_MATCH)
332
333 /* To CLeaR all flags */
334 #define CLR_CTCE_ALLF(c) (c&=~CTCE_WEOF)
335
336 /* Enhanced CTC processing is selected by */
337 /* omitting default MTU bufsize CTCE_MTU_MIN, */
338 /* or by specifying a larger number. The */
339 /* default is equal to 61592, calculated as */
340 /* sizeof(CTCE_SOKPFX) + */
341 /* sizeof(U16=pSokBuf->sCount=2) + */
342 /* 61578 (=0xF08A) */
343 /* the latter number is the largest data */
344 /* sCount seen used by CTC programs to date. */
345 /* If that number would be too small one day, */
346 /* a severe error message will instruct the */
347 /* user to specify an increased MTU bufsize */
348 /* in the device configuration statement. */
349 #define CTCE_MTU_MIN ( (int)( 61578 + sizeof(CTCE_SOKPFX) + sizeof(U16 /* sCount */) ) )
350
351 /**********************************************************************/
352 /* A summary of the Channel-to-Channel command operations this CTCE */
353 /* device emulates can be found in IBM publications SA22-7203-00 in */
354 /* section 2.13, and in SA22-7091-01 sections 2.13 and 3.15. The */
355 /* tables show the device states of both sides, and the influence of */
356 /* CCW commands depending on this state. Our CTCE implemention is */
357 /* assisted by a Finite State Machine (FSM) table closely matching */
358 /* the figures in these prublications. */
359 /* */
360 /* Eeach CTCE side is in a given state at any point in time, which */
361 /* corresponds to the columns in the FSM table, matching columns 0 */
362 /* through 7 in the publications mentionned. Each CCW command has a */
363 /* row in the FSM table. A CCW command received will (1) trigger a */
364 /* transition to a new_state, (2) cause a Unit Status update, and (3) */
365 /* cause a number of actions to be carried out. */
366 /* */
367 /* The FSM table coding is assisted with macro's for the state each */
368 /* CTCE side (x=local, y=remote) can have, matching the FSM column */
369 /* column numbers 0-7: Prepare, Control, Read, Write, Available, */
370 /* Not-ready, X-working (=P/C/R/W) or Int-pending, all represented by */
371 /* a single letter: P, C, R, W, A, N, X, I. Additionally, the CTCE */
372 /* FSM table uses U for Unchanged to cover the case of no state */
373 /* change whatsoever, e.g. for CCW commands SAS, SID, RCD and others. */
374 /* Please see macro's CTCE_NEW_X_STATE & CTCE_NEW_Y_STATE down below. */
375 /**********************************************************************/
376 #define P 0
377 #define C 1
378 #define R 2
379 #define W 3
380 #define A 4
381 #define N 5
382 #define X 6
383 #define I 7
384 #define U 255
385
386 /**********************************************************************/
387 /* Each CTCE FSM table entry contains a macro up to 7 letters long: */
388 /* */
389 /* +---------- new_state = P, C, R, W, A or U */
390 /* |++-------- Unit Status bits encoded with up to two letters: */
391 /* ||| . CD = CE + DE */
392 /* ||| . C = CE */
393 /* ||| . BA = BUSY + ATTN */
394 /* ||| . B = BUSY */
395 /* ||| . UC = Unit Check */
396 /* |||+------- S = Send this commands also to the other (y-)side */
397 /* ||||+------ M = a Matching command for the other (y-)side */
398 /* |||||+----- W = our (x-)side must Wait for a matching command */
399 /* ||||||+---- A = cause Attention interrupt at the other y-side */
400 /* ||||||| */
401 #define PC_S_W { P, CSW_CE , 0, CTCE_SEND | CTCE_WAIT }
402 #define C__S_WA { C, 0 , 0, CTCE_SEND | CTCE_WAIT | CTCE_ATTN }
403 #define R__S_WA { R, 0 , 0, CTCE_SEND | CTCE_WAIT | CTCE_ATTN }
404 #define W__S_WA { W, 0 , 0, CTCE_SEND | CTCE_WAIT | CTCE_ATTN }
405 #define CC_SMW { C, CSW_CE , 0, CTCE_SEND | CTCE_MATCH | CTCE_WAIT }
406 #define R__SMW { R, 0 , 0, CTCE_SEND | CTCE_MATCH | CTCE_WAIT }
407 #define W__SMW { W, 0 , 0, CTCE_SEND | CTCE_MATCH | CTCE_WAIT }
408 #define ACDSM { A, CSW_CE | CSW_DE , 0, CTCE_SEND | CTCE_MATCH }
409 #define ACDS { A, CSW_CE | CSW_DE , 0, CTCE_SEND }
410 #define AUCS { A, CSW_UC , 0, CTCE_SEND }
411 #define CDSM { U, CSW_CE | CSW_DE , 0, CTCE_SEND | CTCE_MATCH }
412 #define CDS { U, CSW_CE | CSW_DE , 0, CTCE_SEND }
413 #define CD { U, CSW_CE | CSW_DE , 0, 0 }
414 #define B { U, CSW_BUSY , 0, 0 }
415 #define BA { U, CSW_BUSY | CSW_ATTN, 0, 0 }
416 #define UC { U, CSW_UC , 0, 0 }
417 #define UCS { U, CSW_UC , 0, CTCE_SEND }
418
419 /**********************************************************************/
420 /* Now finally the CTCE FSM table: */
421 /**********************************************************************/
422 static struct CTCE_FsmEnt {
423 BYTE new_state;
424 BYTE x_unit_stat;
425 BYTE y_unit_stat;
426 BYTE actions;
427 }
428 const CTCE_Fsm[16][8] = {
429 /* cmd/stat P C R W A N X I */
430 /* PRE */ {ACDSM , CD , CD , CD ,PC_S_W , UCS , B , B },
431 /* CTL */ {CC_SMW , BA , BA , BA ,C__S_WA, UCS , B , B },
432 /* RED */ {R__SMW , BA , BA ,ACDSM ,R__S_WA, UCS , B , B },
433 /* WRT */ {W__SMW , BA ,ACDSM , BA ,W__S_WA, UCS , B , B },
434 /* SCB */ { CD ,ACDSM , CD , CD , CD , UCS , B , B },
435 /* nus */ { UC , UC , UC , UC , UC , UC , B , B },
436 /* RBK */ {R__SMW , BA , BA ,ACDSM ,R__S_WA, UCS , B , B },
437 /* WEF */ { CDS , BA ,ACDSM , BA , CDS , UCS , B , B },
438 /* NOP */ { CD , BA , BA , BA , CD , UC , B , B },
439 /* SEM */ { CDS , BA , BA , BA ,ACDS ,AUCS , B , B },
440
441 /* SAS */ { CD , CD , CD , CD , CD , CD , B , B },
442 /* SID */ { CD , CD , CD , CD , CD , CD , B , B },
443 /* RCD */ { CD , CD , CD , CD , CD , CD , B , B },
444
445 /* inv */ { UC , UC , UC , UC , UC , UC , B , B },
446 /* CB0 */ { UC , UC , UC , UC , UC , UC , B , B },
447 /* SBM */ { CDS , BA , BA , BA ,ACDS ,AUCS , B , B }
448 };
449
450 #undef P
451 #undef C
452 #undef R
453 #undef W
454 #undef A
455 #undef N
456 #undef X
457 #undef I
458 #undef U
459
460 #undef PC_S_W
461 #undef C__S_WA
462 #undef R__S_WA
463 #undef W__S_WA
464 #undef CC_SMW
465 #undef R__SMW
466 #undef W__SMW
467 #undef ACDSM
468 #undef ACDS
469 #undef AUCS
470 #undef CDSM
471 #undef CDS
472 #undef CD
473 #undef B
474 #undef BA
475 #undef UC
476 #undef UCS
477
478 #define CTCE_ACTIONS_PRT(s) IS_CTCE_WEOF(s) ? _(" WEOF") : _("") \
479 , IS_CTCE_WAIT(s) ? _(" WAIT") : _("") \
480 , IS_CTCE_MATCH(s) ? _(" MATCH") : _("") \
481 , IS_CTCE_ATTN(s) ? _(" ATTN") : _("")
482
483 #define CTCE_X_STATE_FSM_IDX \
484 ( ( ( pDEVBLK->ctcexState & 0x04 ) == 0x00 ) ? 0x06 : CTCE_STATE( pDEVBLK->ctceyState ) )
485
486 #define CTCE_Y_STATE_FSM_IDX \
487 ( ( ( pDEVBLK->ctceyState & 0x04 ) == 0x00 ) ? 0x06 : CTCE_STATE( pDEVBLK->ctcexState ) )
488
489 #define CTCE_NEW_X_STATE(c) \
490 ( ( CTCE_Fsm[CTCE_CMD( c )][CTCE_X_STATE_FSM_IDX].new_state != 255 ) ? \
491 ( CTCE_Fsm[CTCE_CMD( c )][CTCE_X_STATE_FSM_IDX].new_state ) : \
492 ( pDEVBLK->ctcexState & 0x07 ) )
493
494 #define CTCE_NEW_Y_STATE(c) \
495 ( ( CTCE_Fsm[CTCE_CMD( c )][CTCE_Y_STATE_FSM_IDX].new_state != 255 ) ? \
496 ( CTCE_Fsm[CTCE_CMD( c )][CTCE_Y_STATE_FSM_IDX].new_state ) : \
497 ( pDEVBLK->ctceyState & 0x07 ) )
498
499 #define CTCE_DISABLE_NAGLE
500 #define CTCE_UDP
501
502 /* The following macro's attempt to maximize source commonality between */
503 /* different Hercules versions, whilst adhering to different styles. */
504 #define CTCX_DEVNUM(p) p->devnum
505 #define CTCE_FILENAME pDEVBLK->filename + 2
506
507 /**********************************************************************/
508 /* This table is used by channel.c to determine if a CCW code is an */
509 /* immediate command or not */
510 /* The table is addressed in the DEVHND structure as 'DEVIMM immed' */
511 /* 0 : Command is NOT an immediate command */
512 /* 1 : Command is an immediate command */
513 /* Note : An immediate command is defined as a command which returns */
514 /* CE (channel end) during initialisation (that is, no data is */
515 /* actually transfered). In this case, IL is not indicated for a CCW */
516 /* Format 0 or for a CCW Format 1 when IL Suppression Mode is in */
517 /* effect */
518 /**********************************************************************/
519
520 static BYTE CTCE_immed_commands[256] =
521 {
522 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
523 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, /* 0x */
524 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, /* 1x */
525 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, /* 2x */
526 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, /* 3x */
527 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, /* 4x */
528 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, /* 5x */
529 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, /* 6x */
530 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, /* 7x */
531 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, /* 8x */
532 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, /* 9x */
533 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, /* Ax */
534 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, /* Bx */
535 0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1, /* Cx */
536 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1, /* Dx */
537 0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1, /* Ex */
538 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1 /* Fx */
539 };
540
541 // X0XX X011 No Operation
542 // MMMM M111 Control
543 // 1100 0011 Set Extended Mode
544 // 10XX X011 Set Basic Mode
545 // 1110 0011 Prepare
546 // 1XXX XX01 Write EOF (but not treated as such !)
547
548 // --------------------------------------------------------------------
549 // Device Handler Information Block
550 // --------------------------------------------------------------------
551
552 DEVHND ctcadpt_device_hndinfo =
553 {
554 &CTCX_Init, /* Device Initialisation */
555 &CTCX_ExecuteCCW, /* Device CCW execute */
556 &CTCX_Close, /* Device Close */
557 &CTCX_Query, /* Device Query */
558 NULL, /* Device Start channel pgm */
559 NULL, /* Device End channel pgm */
560 NULL, /* Device Resume channel pgm */
561 NULL, /* Device Suspend channel pgm */
562 NULL, /* Device Read */
563 NULL, /* Device Write */
564 NULL, /* Device Query used */
565 NULL, /* Device Reserve */
566 NULL, /* Device Release */
567 NULL, /* Device Attention */
568 NULL, /* Immediate CCW Codes */
569 NULL, /* Signal Adapter Input */
570 NULL, /* Signal Adapter Output */
571 NULL, /* Hercules suspend */
572 NULL /* Hercules resume */
573 };
574
575 DEVHND ctct_device_hndinfo =
576 {
577 &CTCT_Init, /* Device Initialisation */
578 &CTCX_ExecuteCCW, /* Device CCW execute */
579 &CTCX_Close, /* Device Close */
580 &CTCX_Query, /* Device Query */
581 NULL, /* Device Start channel pgm */
582 NULL, /* Device End channel pgm */
583 NULL, /* Device Resume channel pgm */
584 NULL, /* Device Suspend channel pgm */
585 NULL, /* Device Read */
586 NULL, /* Device Write */
587 NULL, /* Device Query used */
588 NULL, /* Device Reserve */
589 NULL, /* Device Release */
590 NULL, /* Device Attention */
591 NULL, /* Immediate CCW Codes */
592 NULL, /* Signal Adapter Input */
593 NULL, /* Signal Adapter Output */
594 NULL, /* Hercules suspend */
595 NULL /* Hercules resume */
596 };
597
598 DEVHND ctce_device_hndinfo =
599 {
600 &CTCE_Init, /* Device Initialisation */
601 &CTCE_ExecuteCCW, /* Device CCW execute */
602 &CTCX_Close, /* Device Close */
603 &CTCX_Query, /* Device Query */
604 NULL, /* Device Start channel pgm */
605 NULL, /* Device End channel pgm */
606 NULL, /* Device Resume channel pgm */
607 NULL, /* Device Suspend channel pgm */
608 NULL, /* Device Read */
609 NULL, /* Device Write */
610 NULL, /* Device Query used */
611 NULL, /* Device Reserve */
612 NULL, /* Device Release */
613 NULL, /* Device Attention */
614 CTCE_immed_commands, /* Immediate CCW Codes */
615 NULL, /* Signal Adapter Input */
616 NULL, /* Signal Adapter Output */
617 NULL, /* Hercules suspend */
618 NULL /* Hercules resume */
619 };
620
621 DEVHND vmnet_device_hndinfo =
622 {
623 &VMNET_Init, /* Device Initialisation */
624 &CTCX_ExecuteCCW, /* Device CCW execute */
625 &CTCX_Close, /* Device Close */
626 &CTCX_Query, /* Device Query */
627 NULL, /* Device Start channel pgm */
628 NULL, /* Device End channel pgm */
629 NULL, /* Device Resume channel pgm */
630 NULL, /* Device Suspend channel pgm */
631 NULL, /* Device Read */
632 NULL, /* Device Write */
633 NULL, /* Device Query used */
634 NULL, /* Device Reserve */
635 NULL, /* Device Release */
636 NULL, /* Device Attention */
637 NULL, /* Immediate CCW Codes */
638 NULL, /* Signal Adapter Input */
639 NULL, /* Signal Adapter Output */
640 NULL, /* Hercules suspend */
641 NULL /* Hercules resume */
642 };
643
644 extern DEVHND ctci_device_hndinfo;
645 extern DEVHND lcs_device_hndinfo;
646
647 // ====================================================================
648 // Primary Module Entry Points
649 // ====================================================================
650
651 // --------------------------------------------------------------------
652 // Device Initialization Handler (Generic)
653 // --------------------------------------------------------------------
654
CTCX_Init(DEVBLK * pDEVBLK,int argc,char * argv[])655 int CTCX_Init( DEVBLK* pDEVBLK, int argc, char *argv[] )
656 {
657 pDEVBLK->devtype = 0x3088;
658
659 // The first argument is the device emulation type
660 if( argc < 1 )
661 {
662 logmsg( _("HHCCT001E %4.4X: Incorrect number of parameters\n"),
663 pDEVBLK->devnum );
664 return -1;
665 }
666
667 if((pDEVBLK->hnd = hdl_ghnd(argv[0])))
668 {
669 if(pDEVBLK->hnd->init == &CTCX_Init)
670 return -1;
671 free(pDEVBLK->typname);
672 pDEVBLK->typname = strdup(argv[0]);
673 return (pDEVBLK->hnd->init)( pDEVBLK, --argc, ++argv );
674 }
675 logmsg (_("HHCCT034E %s: Unrecognized/unsupported CTC emulation type\n"),
676 argv[0]);
677 return -1;
678 }
679
680 // -------------------------------------------------------------------
681 // Query the device definition (Generic)
682 // -------------------------------------------------------------------
683
CTCX_Query(DEVBLK * pDEVBLK,char ** ppszClass,int iBufLen,char * pBuffer)684 void CTCX_Query( DEVBLK* pDEVBLK,
685 char** ppszClass,
686 int iBufLen,
687 char* pBuffer )
688 {
689 BEGIN_DEVICE_CLASS_QUERY( "CTCA", pDEVBLK, ppszClass, iBufLen, pBuffer );
690
691 snprintf( pBuffer, iBufLen, "%s", pDEVBLK->filename );
692 }
693
694 // -------------------------------------------------------------------
695 // Close the device (Generic)
696 // -------------------------------------------------------------------
697
CTCX_Close(DEVBLK * pDEVBLK)698 int CTCX_Close( DEVBLK* pDEVBLK )
699 {
700
701 // Close the device file (if not already closed)
702 if( pDEVBLK->fd >= 0 )
703 {
704 if (socket_is_socket( pDEVBLK->fd ))
705 close_socket( pDEVBLK->fd );
706 else
707 close( pDEVBLK->fd );
708 pDEVBLK->fd = -1; // indicate we're now closed
709 }
710 return 0;
711 }
712
713 // -------------------------------------------------------------------
714 // Execute a Channel Command Word (Generic)
715 // -------------------------------------------------------------------
716
CTCX_ExecuteCCW(DEVBLK * pDEVBLK,BYTE bCode,BYTE bFlags,BYTE bChained,U16 sCount,BYTE bPrevCode,int iCCWSeq,BYTE * pIOBuf,BYTE * pMore,BYTE * pUnitStat,U16 * pResidual)717 void CTCX_ExecuteCCW( DEVBLK* pDEVBLK, BYTE bCode,
718 BYTE bFlags, BYTE bChained,
719 U16 sCount, BYTE bPrevCode,
720 int iCCWSeq, BYTE* pIOBuf,
721 BYTE* pMore, BYTE* pUnitStat,
722 U16* pResidual )
723 {
724 int iNum; // Number of bytes to move
725 BYTE bOpCode; // CCW opcode with modifier
726 // bits masked off
727
728 UNREFERENCED( bFlags );
729 UNREFERENCED( bChained );
730 UNREFERENCED( bPrevCode );
731 UNREFERENCED( iCCWSeq );
732
733 // Intervention required if the device file is not open
734 if( pDEVBLK->fd < 0 &&
735 !IS_CCW_SENSE( bCode ) &&
736 !IS_CCW_CONTROL( bCode ) )
737 {
738 pDEVBLK->sense[0] = SENSE_IR;
739 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
740 return;
741 }
742
743 // Mask off the modifier bits in the CCW bOpCode
744 if( ( bCode & 0x07 ) == 0x07 )
745 bOpCode = 0x07;
746 else if( ( bCode & 0x03 ) == 0x02 )
747 bOpCode = 0x02;
748 else if( ( bCode & 0x0F ) == 0x0C )
749 bOpCode = 0x0C;
750 else if( ( bCode & 0x03 ) == 0x01 )
751 bOpCode = pDEVBLK->ctcxmode ? ( bCode & 0x83 ) : 0x01;
752 else if( ( bCode & 0x1F ) == 0x14 )
753 bOpCode = 0x14;
754 else if( ( bCode & 0x47 ) == 0x03 )
755 bOpCode = 0x03;
756 else if( ( bCode & 0xC7 ) == 0x43 )
757 bOpCode = 0x43;
758 else
759 bOpCode = bCode;
760
761 // Process depending on CCW bOpCode
762 switch (bOpCode)
763 {
764 case 0x01: // 0MMMMM01 WRITE
765 //------------------------------------------------------------
766 // WRITE
767 //------------------------------------------------------------
768
769 // Return normal status if CCW count is zero
770 if( sCount == 0 )
771 {
772 *pUnitStat = CSW_CE | CSW_DE;
773 break;
774 }
775
776 // Write data and set unit status and residual byte count
777 switch( pDEVBLK->ctctype )
778 {
779 case CTC_CTCT:
780 CTCT_Write( pDEVBLK, sCount, pIOBuf, pUnitStat, pResidual );
781 break;
782 case CTC_VMNET:
783 *pResidual = sCount - VMNET_Write( pDEVBLK, pIOBuf,
784 sCount, pUnitStat );
785 break;
786 }
787 break;
788
789 case 0x81: // 1MMMMM01 WEOF
790 //------------------------------------------------------------
791 // WRITE EOF
792 //------------------------------------------------------------
793
794 // Return normal status
795 *pUnitStat = CSW_CE | CSW_DE;
796 break;
797
798 case 0x02: // MMMMMM10 READ
799 case 0x0C: // MMMM1100 RDBACK
800 // -----------------------------------------------------------
801 // READ & READ BACKWARDS
802 // -----------------------------------------------------------
803
804 // Read data and set unit status and residual byte count
805 switch( pDEVBLK->ctctype )
806 {
807 case CTC_CTCT:
808 CTCT_Read( pDEVBLK, sCount, pIOBuf, pUnitStat, pResidual, pMore );
809 break;
810 case CTC_VMNET:
811 *pResidual = sCount - VMNET_Read( pDEVBLK, pIOBuf,
812 sCount, pUnitStat );
813 break;
814 }
815 break;
816
817 case 0x07: // MMMMM111 CTL
818 // -----------------------------------------------------------
819 // CONTROL
820 // -----------------------------------------------------------
821
822 *pUnitStat = CSW_CE | CSW_DE;
823 break;
824
825 case 0x03: // M0MMM011 NOP
826 // -----------------------------------------------------------
827 // CONTROL NO-OPERATON
828 // -----------------------------------------------------------
829
830 *pUnitStat = CSW_CE | CSW_DE;
831 break;
832
833 case 0x43: // 00XXX011 SBM
834 // -----------------------------------------------------------
835 // SET BASIC MODE
836 // -----------------------------------------------------------
837
838 // Command reject if in basic mode
839 if( pDEVBLK->ctcxmode == 0 )
840 {
841 pDEVBLK->sense[0] = SENSE_CR;
842 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
843
844 break;
845 }
846
847 // Reset extended mode and return normal status
848 pDEVBLK->ctcxmode = 0;
849
850 *pResidual = 0;
851 *pUnitStat = CSW_CE | CSW_DE;
852
853 break;
854
855 case 0xC3: // 11000011 SEM
856 // -----------------------------------------------------------
857 // SET EXTENDED MODE
858 // -----------------------------------------------------------
859
860 pDEVBLK->ctcxmode = 1;
861
862 *pResidual = 0;
863 *pUnitStat = CSW_CE | CSW_DE;
864
865 break;
866
867 case 0xE3: // 11100011
868 // -----------------------------------------------------------
869 // PREPARE (PREP)
870 // -----------------------------------------------------------
871
872 *pUnitStat = CSW_CE | CSW_DE;
873
874 break;
875
876 case 0x14: // XXX10100 SCB
877 // -----------------------------------------------------------
878 // SENSE COMMAND BYTE
879 // -----------------------------------------------------------
880
881 *pUnitStat = CSW_CE | CSW_DE;
882 break;
883
884 case 0x04: // 00000100 SENSE
885 // -----------------------------------------------------------
886 // SENSE
887 // -----------------------------------------------------------
888
889 // Command reject if in basic mode
890 if( pDEVBLK->ctcxmode == 0 )
891 {
892 pDEVBLK->sense[0] = SENSE_CR;
893 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
894 break;
895 }
896
897 // Calculate residual byte count
898 iNum = ( sCount < pDEVBLK->numsense ) ?
899 sCount : pDEVBLK->numsense;
900
901 *pResidual = sCount - iNum;
902
903 if( sCount < pDEVBLK->numsense )
904 *pMore = 1;
905
906 // Copy device sense bytes to channel I/O buffer
907 memcpy( pIOBuf, pDEVBLK->sense, iNum );
908
909 // Clear the device sense bytes
910 memset( pDEVBLK->sense, 0, sizeof( pDEVBLK->sense ) );
911
912 // Return unit status
913 *pUnitStat = CSW_CE | CSW_DE;
914
915 break;
916
917 case 0xE4: // 11100100 SID
918 // -----------------------------------------------------------
919 // SENSE ID
920 // -----------------------------------------------------------
921
922 // Calculate residual byte count
923 iNum = ( sCount < pDEVBLK->numdevid ) ?
924 sCount : pDEVBLK->numdevid;
925
926 *pResidual = sCount - iNum;
927
928 if( sCount < pDEVBLK->numdevid )
929 *pMore = 1;
930
931 // Copy device identifier bytes to channel I/O buffer
932 memcpy( pIOBuf, pDEVBLK->devid, iNum );
933
934 // Return unit status
935 *pUnitStat = CSW_CE | CSW_DE;
936
937 break;
938
939 default:
940 // ------------------------------------------------------------
941 // INVALID OPERATION
942 // ------------------------------------------------------------
943
944 // Set command reject sense byte, and unit check status
945 pDEVBLK->sense[0] = SENSE_CR;
946 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
947 }
948 }
949
950 // ====================================================================
951 // CTCT Support
952 // ====================================================================
953
954 //
955 // CTCT_Init
956 //
957
CTCT_Init(DEVBLK * dev,int argc,char * argv[])958 static int CTCT_Init( DEVBLK *dev, int argc, char *argv[] )
959 {
960 char str[80]; // Thread name
961 int rc; // Return code
962 int mtu; // MTU size (binary)
963 int lport; // Listen port (binary)
964 int rport; // Destination port (binary)
965 char* listenp; // Listening port number
966 char* remotep; // Destination port number
967 char* mtusize; // MTU size (characters)
968 char* remaddr; // Remote IP address
969 struct in_addr ipaddr; // Work area for IP address
970 BYTE c; // Character work area
971 TID tid; // Thread ID for server
972 CTCG_PARMBLK parm; // Parameters for the server
973 char address[20]=""; // temp space for IP address
974
975 dev->devtype = 0x3088;
976
977 dev->ctctype = CTC_CTCT;
978
979 SetSIDInfo( dev, 0x3088, 0x08, 0x3088, 0x01 );
980
981 // Check for correct number of arguments
982 if (argc != 4)
983 {
984 logmsg( _("HHCCT002E %4.4X: Incorrect number of parameters\n"),
985 dev->devnum );
986 return -1;
987 }
988
989 // The first argument is the listening port number
990 listenp = *argv++;
991
992 if( strlen( listenp ) > 5 ||
993 sscanf( listenp, "%u%c", &lport, &c ) != 1 ||
994 lport < 1024 || lport > 65534 )
995 {
996 logmsg( _("HHCCT003E %4.4X: Invalid port number: %s\n"),
997 dev->devnum, listenp );
998 return -1;
999 }
1000
1001 // The second argument is the IP address or hostname of the
1002 // remote side of the point-to-point link
1003 remaddr = *argv++;
1004
1005 if( inet_aton( remaddr, &ipaddr ) == 0 )
1006 {
1007 struct hostent *hp;
1008
1009 if( ( hp = gethostbyname( remaddr ) ) != NULL )
1010 {
1011 memcpy( &ipaddr, hp->h_addr, hp->h_length );
1012 strcpy( address, inet_ntoa( ipaddr ) );
1013 remaddr = address;
1014 }
1015 else
1016 {
1017 logmsg( _("HHCCT004E %4.4X: Invalid IP address %s\n"),
1018 dev->devnum, remaddr );
1019 return -1;
1020 }
1021 }
1022
1023 // The third argument is the destination port number
1024 remotep = *argv++;
1025
1026 if( strlen( remotep ) > 5 ||
1027 sscanf( remotep, "%u%c", &rport, &c ) != 1 ||
1028 rport < 1024 || rport > 65534 )
1029 {
1030 logmsg( _("HHCCT005E %4.4X: Invalid port number: %s\n"),
1031 dev->devnum, remotep );
1032 return -1;
1033 }
1034
1035 // The fourth argument is the maximum transmission unit (MTU) size
1036 mtusize = *argv;
1037
1038 if( strlen( mtusize ) > 5 ||
1039 sscanf( mtusize, "%u%c", &mtu, &c ) != 1 ||
1040 mtu < 46 || mtu > 65536 )
1041 {
1042 logmsg( _("HHCCT006E %4.4X: Invalid MTU size %s\n"),
1043 dev->devnum, mtusize );
1044 return -1;
1045 }
1046
1047 // Set the device buffer size equal to the MTU size
1048 dev->bufsize = mtu;
1049
1050 // Initialize the file descriptor for the socket connection
1051
1052 // It's a little confusing, but we're using a couple of the
1053 // members of the server paramter structure to initiate the
1054 // outgoing connection. Saves a couple of variable declarations,
1055 // though. If we feel strongly about it, we can declare separate
1056 // variables...
1057
1058 // make a TCP socket
1059 parm.listenfd = socket( AF_INET, SOCK_STREAM, 0 );
1060
1061 if( parm.listenfd < 0 )
1062 {
1063 logmsg( _("HHCCT007E %4.4X: Error creating socket: %s\n"),
1064 dev->devnum, strerror( HSO_errno ) );
1065 CTCX_Close( dev );
1066 return -1;
1067 }
1068
1069 // bind socket to our local port
1070 // (might seem like overkill, and usually isn't done, but doing this
1071 // bind() to the local port we configure gives the other end a chance
1072 // at validating the connection request)
1073 memset( &(parm.addr), 0, sizeof( parm.addr ) );
1074 parm.addr.sin_family = AF_INET;
1075 parm.addr.sin_port = htons(lport);
1076 parm.addr.sin_addr.s_addr = htonl(INADDR_ANY);
1077
1078 rc = bind( parm.listenfd,
1079 (struct sockaddr *)&parm.addr,
1080 sizeof( parm.addr ) );
1081 if( rc < 0 )
1082 {
1083 logmsg( _("HHCCT008E %4.4X: Error binding to socket: %s\n"),
1084 dev->devnum, strerror( HSO_errno ) );
1085 CTCX_Close( dev );
1086 return -1;
1087 }
1088
1089 // initiate a connection to the other end
1090 memset( &(parm.addr), 0, sizeof( parm.addr ) );
1091 parm.addr.sin_family = AF_INET;
1092 parm.addr.sin_port = htons(rport);
1093 parm.addr.sin_addr = ipaddr;
1094 rc = connect( parm.listenfd,
1095 (struct sockaddr *)&parm.addr,
1096 sizeof( parm.addr ) );
1097
1098 // if connection was not successful, start a server
1099 if( rc < 0 )
1100 {
1101 // used to pass parameters to the server thread
1102 CTCG_PARMBLK* arg;
1103
1104 logmsg( _("HHCCT009I %4.4X: Connect to %s:%s failed, starting server\n"),
1105 dev->devnum, remaddr, remotep );
1106
1107 // probably don't need to do this, not sure...
1108 close_socket( parm.listenfd );
1109
1110 parm.listenfd = socket( AF_INET, SOCK_STREAM, 0 );
1111
1112 if( parm.listenfd < 0 )
1113 {
1114 logmsg( _("HHCCT010E %4.4X: Error creating socket: %s\n"),
1115 dev->devnum, strerror( HSO_errno ) );
1116 CTCX_Close( dev );
1117 return -1;
1118 }
1119
1120 // set up the listening port
1121 memset( &(parm.addr), 0, sizeof( parm.addr ) );
1122
1123 parm.addr.sin_family = AF_INET;
1124 parm.addr.sin_port = htons(lport);
1125 parm.addr.sin_addr.s_addr = htonl(INADDR_ANY);
1126
1127 if( bind( parm.listenfd,
1128 (struct sockaddr *)&parm.addr,
1129 sizeof( parm.addr ) ) < 0 )
1130 {
1131 logmsg( _("HHCCT011E %4.4X: Error binding to socket: %s\n"),
1132 dev->devnum, strerror( HSO_errno ) );
1133 CTCX_Close( dev );
1134 return -1;
1135 }
1136
1137 if( listen( parm.listenfd, 1 ) < 0 )
1138 {
1139 logmsg( _("HHCCT012E %4.4X: Error on call to listen: %s\n"),
1140 dev->devnum, strerror( HSO_errno ) );
1141 CTCX_Close( dev );
1142 return -1;
1143 }
1144
1145 // we are listening, so create a thread to accept connection
1146 arg = malloc( sizeof( CTCG_PARMBLK ) );
1147 memcpy( arg, &parm, sizeof( parm ) );
1148 arg->dev = dev;
1149 snprintf(str,sizeof(str),"CTCT %4.4X ListenThread",dev->devnum);
1150 str[sizeof(str)-1]=0;
1151 create_thread( &tid, JOINABLE, CTCT_ListenThread, arg, str );
1152 }
1153 else // successfully connected (outbound) to the other end
1154 {
1155 logmsg( _("HHCCT013I %4.4X: Connected to %s:%s\n"),
1156 dev->devnum, remaddr, remotep );
1157 dev->fd = parm.listenfd;
1158 }
1159
1160 // for cosmetics, since we are successfully connected or serving,
1161 // fill in some details for the panel.
1162 sprintf( dev->filename, "%s:%s", remaddr, remotep );
1163
1164 return 0;
1165 }
1166
1167 //
1168 // CTCT_Write
1169 //
1170
CTCT_Write(DEVBLK * pDEVBLK,U16 sCount,BYTE * pIOBuf,BYTE * pUnitStat,U16 * pResidual)1171 static void CTCT_Write( DEVBLK* pDEVBLK, U16 sCount,
1172 BYTE* pIOBuf, BYTE* pUnitStat,
1173 U16* pResidual )
1174 {
1175 PCTCIHDR pFrame; // -> Frame header
1176 PCTCISEG pSegment; // -> Segment in buffer
1177 U16 sOffset; // Offset of next frame
1178 U16 sSegLen; // Current segment length
1179 U16 sDataLen; // Length of IP Frame data
1180 int iPos; // Offset into buffer
1181 U16 i; // Array subscript
1182 int rc; // Return code
1183 BYTE szStackID[33]; // VSE IP stack identity
1184 U32 iStackCmd; // VSE IP stack command
1185
1186 // Check that CCW count is sufficient to contain block header
1187 if( sCount < sizeof( CTCIHDR ) )
1188 {
1189 logmsg( _("HHCCT014E %4.4X: Write CCW count %u is invalid\n"),
1190 pDEVBLK->devnum, sCount );
1191
1192 pDEVBLK->sense[0] = SENSE_DC;
1193 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
1194 return;
1195 }
1196
1197 // Fix-up frame pointer
1198 pFrame = (PCTCIHDR)pIOBuf;
1199
1200 // Extract the frame length from the header
1201 FETCH_HW( sOffset, pFrame->hwOffset );
1202
1203
1204 // Check for special VSE TCP/IP stack command packet
1205 if( sOffset == 0 && sCount == 40 )
1206 {
1207 // Extract the 32-byte stack identity string
1208 for( i = 0;
1209 i < sizeof( szStackID ) - 1 && i < sCount - 4;
1210 i++)
1211 szStackID[i] = guest_to_host( pIOBuf[i+4] );
1212
1213 szStackID[i] = '\0';
1214
1215 // Extract the stack command word
1216 FETCH_FW( iStackCmd, *((FWORD*)&pIOBuf[36]) );
1217
1218 // Display stack command and discard the packet
1219 logmsg( _("HHCCT015I %4.4X: Interface command: %s %8.8X\n"),
1220 pDEVBLK->devnum, szStackID, iStackCmd );
1221
1222 *pUnitStat = CSW_CE | CSW_DE;
1223 *pResidual = 0;
1224 return;
1225 }
1226
1227 // Check for special L/390 initialization packet
1228 if( sOffset == 0 )
1229 {
1230 // Return normal status and discard the packet
1231 *pUnitStat = CSW_CE | CSW_DE;
1232 *pResidual = 0;
1233 return;
1234 }
1235
1236 // Adjust the residual byte count
1237 *pResidual -= sizeof( CTCIHDR );
1238
1239 // Process each segment in the buffer
1240 for( iPos = sizeof( CTCIHDR );
1241 iPos < sOffset;
1242 iPos += sSegLen )
1243 {
1244 // Check that the segment is fully contained within the block
1245 if( iPos + sizeof( CTCISEG ) > sOffset )
1246 {
1247 logmsg( _("HHCCT016E %4.4X: Write buffer contains incomplete "
1248 "segment header at offset %4.4X\n"),
1249 pDEVBLK->devnum, iPos );
1250
1251 pDEVBLK->sense[0] = SENSE_DC;
1252 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
1253 return;
1254 }
1255
1256 // Fix-up segment header in the I/O buffer
1257 pSegment = (PCTCISEG)(pIOBuf + iPos);
1258
1259 // Extract the segment length from the segment header
1260 FETCH_HW( sSegLen, pSegment->hwLength );
1261
1262 // Check that the segment length is valid
1263 if( ( sSegLen < sizeof( CTCISEG ) ) ||
1264 ( iPos + sSegLen > sOffset ) ||
1265 ( iPos + sSegLen > sCount ) )
1266 {
1267 logmsg( _("HHCCT017E %4.4X: Write buffer contains invalid "
1268 "segment length %u at offset %4.4X\n"),
1269 pDEVBLK->devnum, sSegLen, iPos );
1270
1271 pDEVBLK->sense[0] = SENSE_DC;
1272 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
1273 return;
1274 }
1275
1276 // Calculate length of IP frame data
1277 sDataLen = sSegLen - sizeof( CTCISEG );
1278
1279 // Trace the IP packet before sending
1280 if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep )
1281 {
1282 logmsg( _("HHCCT018I %4.4X: Sending packet to %s:\n"),
1283 pDEVBLK->devnum, pDEVBLK->filename );
1284 if( pDEVBLK->ccwtrace )
1285 packet_trace( pSegment->bData, sDataLen );
1286 }
1287
1288 // Write the IP packet
1289 rc = write_socket( pDEVBLK->fd, pSegment->bData, sDataLen );
1290
1291 if( rc < 0 )
1292 {
1293 logmsg( _("HHCCT019E %4.4X: Error writing to %s: %s\n"),
1294 pDEVBLK->devnum, pDEVBLK->filename,
1295 strerror( HSO_errno ) );
1296
1297 pDEVBLK->sense[0] = SENSE_EC;
1298 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
1299 return;
1300 }
1301
1302 // Adjust the residual byte count
1303 *pResidual -= sSegLen;
1304
1305 // We are done if current segment satisfies CCW count
1306 if( iPos + sSegLen == sCount )
1307 {
1308 *pResidual -= sSegLen;
1309 *pUnitStat = CSW_CE | CSW_DE;
1310 return;
1311 }
1312 }
1313
1314 // Set unit status and residual byte count
1315 *pUnitStat = CSW_CE | CSW_DE;
1316 *pResidual = 0;
1317 }
1318
1319 //
1320 // CTCT_Read
1321 //
1322
CTCT_Read(DEVBLK * pDEVBLK,U16 sCount,BYTE * pIOBuf,BYTE * pUnitStat,U16 * pResidual,BYTE * pMore)1323 static void CTCT_Read( DEVBLK* pDEVBLK, U16 sCount,
1324 BYTE* pIOBuf, BYTE* pUnitStat,
1325 U16* pResidual, BYTE* pMore )
1326 {
1327 PCTCIHDR pFrame = NULL; // -> Frame header
1328 PCTCISEG pSegment = NULL; // -> Segment in buffer
1329 fd_set rfds; // Read FD_SET
1330 int iRetVal; // Return code from 'select'
1331 ssize_t iLength = 0;
1332
1333 static struct timeval tv; // Timeout time for 'select'
1334
1335
1336 // Limit how long we should wait for data to come in
1337 FD_ZERO( &rfds );
1338 FD_SET( pDEVBLK->fd, &rfds );
1339
1340 tv.tv_sec = CTC_READ_TIMEOUT_SECS;
1341 tv.tv_usec = 0;
1342
1343 iRetVal = select( pDEVBLK->fd + 1, &rfds, NULL, NULL, &tv );
1344
1345 switch( iRetVal )
1346 {
1347 case 0:
1348 *pUnitStat = CSW_CE | CSW_DE | CSW_UC | CSW_SM;
1349 pDEVBLK->sense[0] = 0;
1350 return;
1351
1352 case -1:
1353 if( HSO_errno == HSO_EINTR )
1354 return;
1355
1356 logmsg( _("HHCCT020E %4.4X: Error reading from %s: %s\n"),
1357 pDEVBLK->devnum, pDEVBLK->filename, strerror( HSO_errno ) );
1358
1359 pDEVBLK->sense[0] = SENSE_EC;
1360 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
1361 return;
1362
1363 default:
1364 break;
1365 }
1366
1367 // Read an IP packet from the TUN device
1368 iLength = read_socket( pDEVBLK->fd, pDEVBLK->buf, pDEVBLK->bufsize );
1369
1370 // Check for other error condition
1371 if( iLength < 0 )
1372 {
1373 logmsg( _("HHCCT021E %4.4X: Error reading from %s: %s\n"),
1374 pDEVBLK->devnum, pDEVBLK->filename, strerror( HSO_errno ) );
1375 pDEVBLK->sense[0] = SENSE_EC;
1376 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
1377 return;
1378 }
1379
1380 // Trace the packet received from the TUN device
1381 if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep )
1382 {
1383 logmsg( _("HHCCT022I %4.4X: Received packet from %s (%d bytes):\n"),
1384 pDEVBLK->devnum, pDEVBLK->filename, iLength );
1385 packet_trace( pDEVBLK->buf, iLength );
1386 }
1387
1388 // Fix-up Frame pointer
1389 pFrame = (PCTCIHDR)pIOBuf;
1390
1391 // Fix-up Segment pointer
1392 pSegment = (PCTCISEG)( pIOBuf + sizeof( CTCIHDR ) );
1393
1394 // Initialize segment
1395 memset( pSegment, 0, iLength + sizeof( CTCISEG ) );
1396
1397 // Update next frame offset
1398 STORE_HW( pFrame->hwOffset,
1399 iLength + sizeof( CTCIHDR ) + sizeof( CTCISEG ) );
1400
1401 // Store segment length
1402 STORE_HW( pSegment->hwLength, iLength + sizeof( CTCISEG ) );
1403
1404 // Store Frame type
1405 STORE_HW( pSegment->hwType, ETH_TYPE_IP );
1406
1407 // Copy data
1408 memcpy( pSegment->bData, pDEVBLK->buf, iLength );
1409
1410 // Fix-up frame pointer and terminate block
1411 pFrame = (PCTCIHDR)( pIOBuf + sizeof( CTCIHDR ) +
1412 sizeof( CTCISEG ) + iLength );
1413 STORE_HW( pFrame->hwOffset, 0x0000 );
1414
1415 // Calculate #of bytes returned including two slack bytes
1416 iLength += sizeof( CTCIHDR ) + sizeof( CTCISEG ) + 2;
1417
1418 if( sCount < iLength )
1419 {
1420 *pMore = 1;
1421 *pResidual = 0;
1422
1423 iLength = sCount;
1424 }
1425 else
1426 {
1427 *pMore = 0;
1428 *pResidual -= iLength;
1429 }
1430
1431 // Set unit status
1432 *pUnitStat = CSW_CE | CSW_DE;
1433 }
1434
1435 //
1436 // CTCT_ListenThread
1437 //
1438
CTCT_ListenThread(void * argp)1439 static void* CTCT_ListenThread( void* argp )
1440 {
1441 int connfd;
1442 socklen_t servlen;
1443 char str[80];
1444 CTCG_PARMBLK parm;
1445
1446 // set up the parameters passed via create_thread
1447 parm = *((CTCG_PARMBLK*) argp);
1448 free( argp );
1449
1450 for( ; ; )
1451 {
1452 servlen = sizeof(parm.addr);
1453
1454 // await a connection
1455 connfd = accept( parm.listenfd,
1456 (struct sockaddr *)&parm.addr,
1457 &servlen );
1458
1459 sprintf( str, "%s:%d",
1460 inet_ntoa( parm.addr.sin_addr ),
1461 ntohs( parm.addr.sin_port ) );
1462
1463 if( strcmp( str, parm.dev->filename ) != 0 )
1464 {
1465 logmsg( _("HHCCT023E %4.4X: Incorrect client or config error\n"
1466 " Config=%s, connecting client=%s\n"),
1467 parm.dev->devnum,
1468 parm.dev->filename, str);
1469 close_socket( connfd );
1470 }
1471 else
1472 {
1473 parm.dev->fd = connfd;
1474 }
1475
1476 // Ok, so having done that we're going to loop back to the
1477 // accept(). This was meant to handle the connection failing
1478 // at the other end; this end will be ready to accept another
1479 // connection. Although this will happen, I'm sure you can
1480 // see the possibility for bad things to occur (eg if another
1481 // Hercules tries to connect). This will also be fixed RSN.
1482 }
1483
1484 return NULL; // make compiler happy
1485 }
1486
1487 // ====================================================================
1488 // VMNET Support -- written by Willem Konynenberg
1489 // ====================================================================
1490
1491 /*-------------------------------------------------------------------*/
1492 /* Definitions for SLIP encapsulation */
1493 /*-------------------------------------------------------------------*/
1494 #define SLIP_END 0300
1495 #define SLIP_ESC 0333
1496 #define SLIP_ESC_END 0334
1497 #define SLIP_ESC_ESC 0335
1498
1499 /*-------------------------------------------------------------------*/
1500 /* Functions to support vmnet written by Willem Konynenberg */
1501 /*-------------------------------------------------------------------*/
start_vmnet(DEVBLK * dev,DEVBLK * xdev,int argc,char * argv[])1502 static int start_vmnet(DEVBLK *dev, DEVBLK *xdev, int argc, char *argv[])
1503 {
1504 int sockfd[2];
1505 int r, i;
1506 char *ipaddress;
1507
1508 if (argc < 2) {
1509 logmsg (_("HHCCT024E %4.4X: Not enough arguments to start vmnet\n"),
1510 dev->devnum);
1511 return -1;
1512 }
1513
1514 ipaddress = argv[0];
1515 argc--;
1516 argv++;
1517
1518 if (socketpair (AF_UNIX, SOCK_STREAM, 0, sockfd) < 0) {
1519 logmsg (_("HHCCT025E %4.4X: Failed: socketpair: %s\n"),
1520 dev->devnum, strerror(errno));
1521 return -1;
1522 }
1523
1524 r = fork ();
1525
1526 if (r < 0) {
1527 logmsg (_("HHCCT026E %4.4X: Failed: fork: %s\n"),
1528 dev->devnum, strerror(errno));
1529 return -1;
1530 } else if (r == 0) {
1531 /* child */
1532 close (0);
1533 close (1);
1534 dup (sockfd[1]);
1535 dup (sockfd[1]);
1536 r = (sockfd[0] > sockfd[1]) ? sockfd[0] : sockfd[1];
1537 for (i = 3; i <= r; i++) {
1538 close (i);
1539 }
1540
1541 /* the ugly cast is to silence a compiler warning due to const */
1542 execv (argv[0], (EXECV_ARG2_ARGV_T)argv);
1543
1544 exit (1);
1545 }
1546
1547 close (sockfd[1]);
1548 dev->fd = sockfd[0];
1549 xdev->fd = sockfd[0];
1550
1551 /* We just blindly copy these out in the hope vmnet will pick them
1552 * up correctly. I don't feel like implementing a complete login
1553 * scripting facility here...
1554 */
1555 write(dev->fd, ipaddress, strlen(ipaddress));
1556 write(dev->fd, "\n", 1);
1557 return 0;
1558 }
1559
VMNET_Init(DEVBLK * dev,int argc,char * argv[])1560 static int VMNET_Init(DEVBLK *dev, int argc, char *argv[])
1561 {
1562 U16 xdevnum; /* Pair device devnum */
1563 DEVBLK *xdev; /* Pair device */
1564 int rc;
1565 U16 lcss;
1566
1567 dev->devtype = 0x3088;
1568
1569 /* parameters for network CTC are:
1570 * devnum of the other CTC device of the pair
1571 * ipaddress
1572 * vmnet command line
1573 *
1574 * CTC adapters are used in pairs, one for READ, one for WRITE.
1575 * The vmnet is only initialised when both are initialised.
1576 */
1577 if (argc < 3) {
1578 logmsg(_("HHCCT027E %4.4X: Not enough parameters\n"), dev->devnum);
1579 return -1;
1580 }
1581 rc=parse_single_devnum(argv[0],&lcss,&xdevnum);
1582 if (rc<0)
1583 {
1584 logmsg(_("HHCCT028E %d:%4.4X: Bad device number '%s'\n"),
1585 SSID_TO_LCSS(dev->ssid), dev->devnum, argv[0]);
1586 return -1;
1587 }
1588 xdev = find_device_by_devnum(lcss,xdevnum);
1589 if (xdev != NULL) {
1590 if (start_vmnet(dev, xdev, argc - 1, &argv[1]))
1591 return -1;
1592 }
1593 strcpy(dev->filename, "vmnet");
1594
1595 /* Set the control unit type */
1596 /* Linux/390 currently only supports 3088 model 2 CTCA and ESCON */
1597 dev->ctctype = CTC_VMNET;
1598
1599 SetSIDInfo( dev, 0x3088, 0x08, 0x3088, 0x01 );
1600
1601 /* Initialize the device dependent fields */
1602 dev->ctcpos = 0;
1603 dev->ctcrem = 0;
1604
1605 /* Set length of buffer */
1606 /* This size guarantees we can write a full iobuf of 65536
1607 * as a SLIP packet in a single write. Probably overkill... */
1608 dev->bufsize = 65536 * 2 + 1;
1609 return 0;
1610 }
1611
VMNET_Write(DEVBLK * dev,BYTE * iobuf,U16 count,BYTE * unitstat)1612 static int VMNET_Write(DEVBLK *dev, BYTE *iobuf, U16 count, BYTE *unitstat)
1613 {
1614 int blklen = (iobuf[0]<<8) | iobuf[1];
1615 int pktlen;
1616 BYTE *p = iobuf + 2;
1617 BYTE *buffer = dev->buf;
1618 int len = 0, rem;
1619
1620 if (count < blklen) {
1621 logmsg (_("HHCCT029E %4.4X: bad block length: %d < %d\n"),
1622 dev->devnum, count, blklen);
1623 blklen = count;
1624 }
1625 while (p < iobuf + blklen) {
1626 pktlen = (p[0]<<8) | p[1];
1627
1628 rem = iobuf + blklen - p;
1629
1630 if (rem < pktlen) {
1631 logmsg (_("HHCCT030E %4.4X: bad packet length: %d < %d\n"),
1632 dev->devnum, rem, pktlen);
1633 pktlen = rem;
1634 }
1635 if (pktlen < 6) {
1636 logmsg (_("HHCCT031E %4.4X: bad packet length: %d < 6\n"),
1637 dev->devnum, pktlen);
1638 pktlen = 6;
1639 }
1640
1641 pktlen -= 6;
1642 p += 6;
1643
1644 while (pktlen--) {
1645 switch (*p) {
1646 case SLIP_END:
1647 buffer[len++] = SLIP_ESC;
1648 buffer[len++] = SLIP_ESC_END;
1649 break;
1650 case SLIP_ESC:
1651 buffer[len++] = SLIP_ESC;
1652 buffer[len++] = SLIP_ESC_ESC;
1653 break;
1654 default:
1655 buffer[len++] = *p;
1656 break;
1657 }
1658 p++;
1659 }
1660 buffer[len++] = SLIP_END;
1661 write(dev->fd, buffer, len); /* should check error conditions? */
1662 len = 0;
1663 }
1664
1665 *unitstat = CSW_CE | CSW_DE;
1666
1667 return count;
1668 }
1669
bufgetc(DEVBLK * dev,int blocking)1670 static int bufgetc(DEVBLK *dev, int blocking)
1671 {
1672 BYTE *bufp = dev->buf + dev->ctcpos, *bufend = bufp + dev->ctcrem;
1673 int n;
1674
1675 if (bufp >= bufend) {
1676 if (blocking == 0) return -1;
1677 do {
1678 n = read(dev->fd, dev->buf, dev->bufsize);
1679 if (n <= 0) {
1680 if (n == 0) {
1681 /* VMnet died on us. */
1682 logmsg (_("HHCCT032E %4.4X: Error: EOF on read, "
1683 "CTC network down\n"),
1684 dev->devnum);
1685 /* -2 will cause an error status to be set */
1686 return -2;
1687 }
1688 if( n == EINTR )
1689 return -3;
1690 logmsg (_("HHCCT033E %4.4X: Error: read: %s\n"),
1691 dev->devnum, strerror(errno));
1692 SLEEP(2);
1693 }
1694 } while (n <= 0);
1695 dev->ctcrem = n;
1696 bufend = &dev->buf[n];
1697 dev->ctclastpos = dev->ctclastrem = dev->ctcpos = 0;
1698 bufp = dev->buf;
1699 }
1700
1701 dev->ctcpos++;
1702 dev->ctcrem--;
1703
1704 return *bufp;
1705 }
1706
setblkheader(BYTE * iobuf,int buflen)1707 static void setblkheader(BYTE *iobuf, int buflen)
1708 {
1709 iobuf[0] = (buflen >> 8) & 0xFF;
1710 iobuf[1] = buflen & 0xFF;
1711 }
1712
setpktheader(BYTE * iobuf,int packetpos,int packetlen)1713 static void setpktheader(BYTE *iobuf, int packetpos, int packetlen)
1714 {
1715 iobuf[packetpos] = (packetlen >> 8) & 0xFF;
1716 iobuf[packetpos+1] = packetlen & 0xFF;
1717 iobuf[packetpos+2] = 0x08;
1718 iobuf[packetpos+3] = 0;
1719 iobuf[packetpos+4] = 0;
1720 iobuf[packetpos+5] = 0;
1721 }
1722
1723 /* read data from the CTC connection.
1724 * If a packet overflows the iobuf or the read buffer runs out, there are
1725 * 2 possibilities:
1726 * - block has single packet: continue reading packet, drop bytes,
1727 * then return truncated packet.
1728 * - block has multiple packets: back up on last packet and return
1729 * what we have. Do this last packet in the next IO.
1730 */
VMNET_Read(DEVBLK * dev,BYTE * iobuf,U16 count,BYTE * unitstat)1731 static int VMNET_Read(DEVBLK *dev, BYTE *iobuf, U16 count, BYTE *unitstat)
1732 {
1733 int c; /* next byte to process */
1734 int len = 8; /* length of block */
1735 int lastlen = 2; /* block length at last pckt */
1736
1737 dev->ctclastpos = dev->ctcpos;
1738 dev->ctclastrem = dev->ctcrem;
1739
1740 while (1) {
1741 c = bufgetc(dev, lastlen == 2);
1742 if (c < 0) {
1743 if(c == -3)
1744 return 0;
1745 /* End of input buffer. Return what we have. */
1746
1747 setblkheader (iobuf, lastlen);
1748
1749 dev->ctcpos = dev->ctclastpos;
1750 dev->ctcrem = dev->ctclastrem;
1751
1752 *unitstat = CSW_CE | CSW_DE | (c == -2 ? CSW_UX : 0);
1753
1754 return lastlen;
1755 }
1756 switch (c) {
1757 case SLIP_END:
1758 if (len > 8) {
1759 /* End of packet. Set up for next. */
1760
1761 setpktheader (iobuf, lastlen, len-lastlen);
1762
1763 dev->ctclastpos = dev->ctcpos;
1764 dev->ctclastrem = dev->ctcrem;
1765 lastlen = len;
1766
1767 len += 6;
1768 }
1769 break;
1770 case SLIP_ESC:
1771 c = bufgetc(dev, lastlen == 2);
1772 if (c < 0) {
1773 if(c == -3)
1774 return 0;
1775 /* End of input buffer. Return what we have. */
1776
1777 setblkheader (iobuf, lastlen);
1778
1779 dev->ctcpos = dev->ctclastpos;
1780 dev->ctcrem = dev->ctclastrem;
1781
1782 *unitstat = CSW_CE | CSW_DE | (c == -2 ? CSW_UX : 0);
1783
1784 return lastlen;
1785 }
1786 switch (c) {
1787 case SLIP_ESC_END:
1788 c = SLIP_END;
1789 break;
1790 case SLIP_ESC_ESC:
1791 c = SLIP_ESC;
1792 break;
1793 }
1794 /* FALLTHRU */
1795 default:
1796 if (len < count) {
1797 iobuf[len++] = c;
1798 } else if (lastlen > 2) {
1799 /* IO buffer is full and we have data to return */
1800
1801 setblkheader (iobuf, lastlen);
1802
1803 dev->ctcpos = dev->ctclastpos;
1804 dev->ctcrem = dev->ctclastrem;
1805
1806 *unitstat = CSW_CE | CSW_DE | (c == -2 ? CSW_UX : 0);
1807
1808 return lastlen;
1809 } /* else truncate end of very large single packet... */
1810 }
1811 }
1812 }
1813 /*-------------------------------------------------------------------*/
1814 /* End of VMNET functions written by Willem Konynenberg */
1815 /*-------------------------------------------------------------------*/
1816
1817 // ====================================================================
1818 // CTCE Support
1819 // ====================================================================
1820
1821 // CTC Enhanced
1822 // ============
1823 // Enhanced CTC functionality is designed to emulate real
1824 // 3088 CTC Adapter hardware, using a pair of TCP sockets
1825 // with a likewise configured Hercules instance on a
1826 // different PC (or same PC). The new device type is CTCE.
1827
1828 // The implementation is based mostly on IBM publications,
1829 // "ESCON Channel-to-Channel Adapter", SA22-7203-00, and
1830 // also "Channel-to-Channel Adapter", SA22-7091-01, although
1831 // no claim for completeness of this implemenation is feasible.
1832
1833 // The CTCE configuration is similar to the CTCT device. The
1834 // MTU bufsize parameter is optional, but when specified must be
1835 // >= CTCE_MTU_MIN (=61592). This is the default value when omitted.
1836 // (Please note that 61592 = sizeof(CTCE_SOKPFX) + sizeof(sCount) + 0xF08A
1837 // the latter being the maximum sCount experienced in CTC CCW programs.)
1838
1839 // CTCE requires an even-odd pair of port numbers per device side
1840 // but only the even port numbers are to be configured; the odd
1841 // numbers are just derived by adding 1 to the (configured) even
1842 // port numbers. The socket connection pairs cross-connect, the
1843 // arrows showing the send->receive direction :
1844 //
1845 // x-lport-even -> y-rport-odd
1846 // x-lport-odd <- y-rport-even
1847 //
1848 // A sample CTCE device configuration is shown below:
1849 //
1850 // Hercules PC Host A with IP address 192.168.1.100 :
1851 //
1852 // 0E40 CTCE 30880 192.168.1.200 30880
1853 // 0E41 CTCE 30882 192.168.1.200 30882
1854 //
1855 // Hercules PC Host B with IP address 192.168.1.200 :
1856 //
1857 // 0E40 CTCE 30880 192.168.1.100 30880
1858 // 0E41 CTCE 30882 192.168.1.100 30882
1859
1860 // -------------------------------------------------------------------
1861 // Execute a Channel Command Word (CTCE)
1862 // -------------------------------------------------------------------
1863
CTCE_ExecuteCCW(DEVBLK * pDEVBLK,BYTE bCode,BYTE bFlags,BYTE bChained,U16 sCount,BYTE bPrevCode,int iCCWSeq,BYTE * pIOBuf,BYTE * pMore,BYTE * pUnitStat,U16 * pResidual)1864 void CTCE_ExecuteCCW( DEVBLK* pDEVBLK, BYTE bCode,
1865 BYTE bFlags, BYTE bChained,
1866 U16 sCount, BYTE bPrevCode,
1867 int iCCWSeq, BYTE* pIOBuf,
1868 BYTE* pMore, BYTE* pUnitStat,
1869 U16* pResidual )
1870 {
1871 int iNum; // Number of bytes to move
1872 CTCE_PARMBLK parm; // Parameters for the server
1873 // as in CTCE_Init, used here for the client side
1874 int optval; // Argument for setsockopt
1875 char* remaddr; // Remote IP address
1876 char address[20]=""; // temp space for IP address
1877 int rc; // Return code
1878 CTCE_INFO CTCE_Info; // CTCE information (also for tracing)
1879
1880 UNREFERENCED( bChained );
1881 UNREFERENCED( bPrevCode );
1882 UNREFERENCED( iCCWSeq );
1883 UNREFERENCED( pMore );
1884
1885 // Initialise our CTCE_Info and save the previous x- and y-states in it.
1886 CTCE_Info.wait_rc = 0;
1887 CTCE_Info.de_ready = 0;
1888 CTCE_Info.de_ready_attn_rc = 0;
1889 CTCE_Info.working_attn_rc = 0;
1890 CTCE_Info.busy_waits = 0;
1891 CTCE_Info.sent = 0;
1892 CTCE_Info.con_lost = 0;
1893 CTCE_Info.con_won = 0;
1894 CTCE_Info.sok_buf_len = 0;
1895 CTCE_Info.state_x_prev = pDEVBLK->ctcexState;
1896 CTCE_Info.state_y_prev = pDEVBLK->ctceyState;
1897
1898 // Connect to the partner CTCE device if the device file is not open
1899 if (pDEVBLK->fd < 0)
1900 {
1901
1902 // It's a little confusing, but we're using a couple of the
1903 // members of the server paramter structure to initiate the
1904 // outgoing connection. Saves a couple of variable declarations,
1905 // though. If we feel strongly about it, we can declare separate
1906 // variables...
1907
1908 // make a TCP socket
1909 parm.listenfd[0] = socket(AF_INET, SOCK_STREAM, 0);
1910 if( parm.listenfd[0] < 0 )
1911 {
1912 logmsg( _("HHCCT050E %04X CTCE: Error creating socket: %s\n"),
1913 CTCX_DEVNUM( pDEVBLK ), strerror( HSO_errno ) );
1914 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
1915 release_lock( &pDEVBLK->lock );
1916 return;
1917 }
1918
1919 // Allow previous instance of socket to be reused
1920 optval = 1;
1921 setsockopt( parm.listenfd[0], SOL_SOCKET, SO_REUSEADDR,
1922 ( GETSET_SOCKOPT_T* )&optval, sizeof( optval ) );
1923
1924 #if defined(CTCE_DISABLE_NAGLE)
1925 optval = 1;
1926 rc = setsockopt( parm.listenfd[0], IPPROTO_TCP, TCP_NODELAY,
1927 ( char* )&optval, sizeof( optval ) );
1928 if( rc < 0 )
1929 {
1930 logmsg( _("HHCCT051E %04X CTCE: TCP_NODELAY error for socket (port %d): %s\n"),
1931 CTCX_DEVNUM( pDEVBLK ), pDEVBLK->ctce_lport, strerror(HSO_errno));
1932 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
1933 release_lock(&pDEVBLK->lock);
1934 return;
1935 }
1936 #endif
1937
1938 // bind socket to our local port
1939 // (might seem like overkill, and usually isn't done, but doing this
1940 // bind() to the local port we configure gives the other end a chance
1941 // at validating the connection request)
1942 memset( &( parm.addr ), 0, sizeof( parm.addr ) );
1943 parm.addr.sin_family = AF_INET;
1944 parm.addr.sin_port = htons( pDEVBLK->ctce_lport );
1945 parm.addr.sin_addr.s_addr = htonl( INADDR_ANY );
1946
1947 rc = bind( parm.listenfd[0],
1948 ( struct sockaddr * )&parm.addr,
1949 sizeof( parm.addr ) );
1950 if( rc < 0 )
1951 {
1952 logmsg( _("HHCCT052E %04X CTCE: Error binding to socket (port %d): %s\n"),
1953 CTCX_DEVNUM( pDEVBLK ), pDEVBLK->ctce_lport, strerror( HSO_errno ) );
1954 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
1955 release_lock( &pDEVBLK->lock );
1956 return;
1957 }
1958 strcpy( address, inet_ntoa( pDEVBLK->ctce_ipaddr ) );
1959 remaddr = address;
1960
1961 // initiate a connection to the other end
1962 memset( &( parm.addr ), 0, sizeof( parm.addr ) );
1963 parm.addr.sin_family = AF_INET;
1964
1965 // the even (=read) port must connect to the odd (=write) port
1966 // at the other side and vice-versa
1967 parm.addr.sin_port = htons(pDEVBLK->ctce_rport + 1 );
1968 parm.addr.sin_addr = pDEVBLK->ctce_ipaddr;
1969
1970 // We connect() but with a timeout value of 1000000 usec = 1 sec
1971 rc = CTCE_Connect_Timeout( parm.listenfd[0],
1972 ( struct sockaddr * )&parm.addr,
1973 sizeof( parm.addr), 1000000 );
1974
1975 // if connection was not successful, then we may retry later on when the other side becomes ready.
1976 if( rc < 0 )
1977 {
1978 logmsg( _("HHCCT053I %04X CTCE: Connect error :%d -> %s:%d, retry is possible\n"),
1979 CTCX_DEVNUM( pDEVBLK ), pDEVBLK->ctce_lport, remaddr, pDEVBLK->ctce_rport + 1 );
1980 }
1981 else // successfully connected to the other end
1982 {
1983 logmsg( _("HHCCT054I %04X CTCE: Started outbound connection :%d -> %s:%d\n"),
1984 CTCX_DEVNUM( pDEVBLK ), pDEVBLK->ctce_lport, remaddr, pDEVBLK->ctce_rport + 1 );
1985
1986 // The even local port (form the config) is for writing
1987 pDEVBLK->fd = parm.listenfd[0];
1988 }
1989 }
1990
1991 // The contention winning CTCE side initially is the first one to
1992 // attempt commands; each matching SCB command sent sets this as well.
1993 if( ( pDEVBLK->fd < 0 ) || ( pDEVBLK->ctcefd < 0 ) )
1994 {
1995 pDEVBLK->ctce_contention_loser = 0;
1996
1997 // Intervention required if the device file is not open
1998 if( !IS_CCW_SENSE( bCode ) &&
1999 !IS_CCW_CONTROL( bCode ) )
2000 {
2001 pDEVBLK->sense[0] = SENSE_IR;
2002 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
2003 return;
2004 }
2005 }
2006
2007 // Changes to DEVBLK are lock protected as the CTCE_RecvThread
2008 // might update as well.
2009 obtain_lock( &pDEVBLK->lock );
2010
2011 // The CCW Flags Command Chaining indicator being set indicates
2012 // that a CCW Program is in progress. The last CCW in the chain
2013 // has this flag turned off.
2014 pDEVBLK->ctce_ccw_flags_cc = ( ( bFlags & CCW_FLAGS_CC ) != 0 );
2015
2016 // Copy control command byte in x command register
2017 pDEVBLK->ctcexCmd = bCode;
2018
2019 // A valid Set Extended / Base Mode (SEM / SBM) command will have
2020 // an immediate effect so that it can from then on be handled as
2021 // a NOP command. Valid means x-state Available and y-state
2022 // not in Working(D) with Control, Read or Write (CRW).
2023 // Please note that the Basic to Extended mode switch influences
2024 // the CTCS FSM table indexing which is why this is done up front.
2025 // So we set Extended mode and enforce Available x-state.
2026 if( IS_CTCE_CCW_SEM( pDEVBLK->ctcexCmd ) &&
2027 IS_CTCE_YAV( pDEVBLK->ctcexState ) &&
2028 !IS_CTCE_CRW( pDEVBLK->ctceyState ) )
2029 {
2030 pDEVBLK->ctcxmode = 1;
2031 SET_CTCE_YAV( pDEVBLK->ctcexState );
2032 }
2033
2034 // Or we just set Base mode.
2035 else if( IS_CTCE_CCW_SBM( pDEVBLK->ctcexCmd ) &&
2036 IS_CTCE_YAV( pDEVBLK->ctcexState ) &&
2037 !IS_CTCE_CRW( pDEVBLK->ctceyState ) )
2038 {
2039 pDEVBLK->ctcxmode = 0;
2040 }
2041
2042 // The new X-state and transition actions are derived from the FSM table.
2043 CTCE_Info.state_new = CTCE_NEW_X_STATE( pDEVBLK->ctcexCmd );
2044 CTCE_Info.actions = CTCE_Fsm[CTCE_CMD( pDEVBLK->ctcexCmd )][CTCE_X_STATE_FSM_IDX].actions;
2045 CTCE_Info.x_unit_stat = CTCE_Fsm[CTCE_CMD( pDEVBLK->ctcexCmd )][CTCE_X_STATE_FSM_IDX].x_unit_stat;
2046
2047 *pUnitStat = CTCE_Fsm[CTCE_CMD( pDEVBLK->ctcexCmd )][CTCE_X_STATE_FSM_IDX].x_unit_stat;
2048
2049 // We avoid a possible command collision between a SEM command and
2050 // a WRITE command already issued by the other side but not received
2051 // yet. The BUSY+ATTN response to that would cause an endless loop,
2052 // which we simple avoid by replacing it with CE+DE.
2053 if( IS_CTCE_CCW_SEM( pDEVBLK->ctcexCmd ) &&
2054 IS_CTCE_YAV( pDEVBLK->ctcexState ) &&
2055 *pUnitStat == ( CSW_BUSY | CSW_ATTN ) )
2056 {
2057 *pUnitStat = CSW_CE | CSW_DE;
2058 }
2059
2060 // If a READ or READ_BACKWARD command is received whilst the WEOF
2061 // bit is set then the sole case for a Unit Exception applies.
2062 else if( IS_CTCE_WEOF( pDEVBLK->ctcexState ) &&
2063 IS_CTCE_CCW_RDA( pDEVBLK->ctcexCmd ) )
2064 {
2065 CLR_CTCE_WEOF( pDEVBLK->ctcexState );
2066 *pResidual = 0;
2067 *pUnitStat = CSW_CE | CSW_DE | CSW_UX;
2068 }
2069
2070 // Otherwise in case the CTCE device is not busy actions may result.
2071 else if( !( CTCE_Info.x_unit_stat & CSW_BUSY ) )
2072 {
2073 CLR_CTCE_WEOF( pDEVBLK->ctcexState );
2074
2075 // Process depending on the CCW command.
2076 switch ( CTCE_CMD( pDEVBLK->ctcexCmd ) )
2077 {
2078
2079 // Most of the CTCE commands processing (if any at all)
2080 // takes place in CTCE_Send and CTCE_RECV down below.
2081 case CTCE_PREPARE:
2082 case CTCE_CONTROL:
2083 case CTCE_READ:
2084 case CTCE_WRITE:
2085 case CTCE_READ_BACKWARD:
2086 case CTCE_WRITE_END_OF_FILE:
2087 case CTCE_NO_OPERATION:
2088 case CTCE_SET_EXTENDED_MODE:
2089 case CTCE_SET_BASIC_MODE:
2090 break;
2091
2092 case CTCE_SENSE_COMMAND_BYTE:
2093
2094 // In y-state available we return 0 otherwise the last y-side command.
2095 *pIOBuf = ( IS_CTCE_YAV( pDEVBLK->ctceyState ) ) ?
2096 0 : pDEVBLK->ctceyCmdSCB;
2097 CTCE_Info.scb = *pIOBuf;
2098 *pResidual = sCount - 1;
2099 break;
2100
2101 case CTCE_SENSE_ADAPTER_STATE:
2102
2103 // Calculate residual byte count
2104 iNum = ( sCount < pDEVBLK->numsense ) ?
2105 sCount : pDEVBLK->numsense;
2106 *pResidual = sCount - iNum;
2107
2108 // Copy device sense bytes to channel I/O buffer
2109 memcpy( pIOBuf, pDEVBLK->sense, iNum );
2110
2111 // Clear the device sense bytes
2112 memset( pDEVBLK->sense, 0, sizeof( pDEVBLK->sense ) );
2113 break;
2114
2115 case CTCE_SENSE_ID:
2116
2117 // Calculate residual byte count
2118 iNum = ( sCount < pDEVBLK->numdevid ) ?
2119 sCount : pDEVBLK->numdevid;
2120 *pResidual = sCount - iNum;
2121
2122 // Copy device identifier bytes to channel I/O buffer
2123 memcpy( pIOBuf, pDEVBLK->devid, iNum );
2124 break;
2125
2126 // Invalid commands
2127 // (or never experienced / tested / supported ones)
2128 case CTCE_READ_CONFIG_DATA:
2129 default:
2130
2131 // Signalling invalid commands using Unit Check with a
2132 // Command Reject sense code for this CTCE device failed.
2133 // (MVS results were a WAIT 064 RSN 9 during NIP.)
2134 // An Interface Control Check would probably be needed but
2135 // we do not know how to generate that, so we use SENSE_EC.
2136 //
2137 // pDEVBLK->sense[0] = SENSE_CR;
2138
2139 pDEVBLK->sense[0] = SENSE_EC;
2140 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
2141
2142 } // switch ( CTCE_CMD( pDEVBLK->ctcexCMD ) )
2143
2144 // In most cases we need to inform the other (y-)side so we SEND
2145 // our command (and data) to the other side. During this process
2146 // and any response received, all other actions take place.
2147 if( IS_CTCE_SEND( CTCE_Info.actions ) )
2148 {
2149 CTCE_Send( pDEVBLK, sCount, pIOBuf, pUnitStat, pResidual, &CTCE_Info );
2150
2151 // In case we sent a matching SCB command, this side becomes
2152 // the contention winner side; the receiver updates accordingly.
2153 if( IS_CTCE_CCW_SCB( pDEVBLK->ctcexCmd ) && CTCE_Info.sent )
2154 {
2155 pDEVBLK->ctce_contention_loser = 0;
2156 }
2157 }
2158
2159 // This (x-)side will leave the Not Ready state.
2160 if( IS_CTCE_YNR( pDEVBLK->ctcexState ) )
2161 {
2162 SET_CTCE_YAV( pDEVBLK->ctcexState );
2163 }
2164
2165 } // if( !( CTCE_Info.x_unit_stat & CSW_BUSY ) )
2166
2167 // We merge a Unit Check in case the Y state is Not Ready.
2168 // But only when pUnitStat is still 0 or just Busy (no Attn).
2169 if( IS_CTCE_YNR( pDEVBLK -> ctceyState ) &&
2170 ( ( *pUnitStat & (~ CSW_BUSY ) ) == 0 ) )
2171 {
2172 *pUnitStat |= CSW_UC;
2173 pDEVBLK->sense[0] = SENSE_IR;
2174 }
2175
2176 // Produce a CTCE Trace logging if requested, noting that for the
2177 // IS_CTCE_WAIT cases such a logging is produced prior to the WAIT,
2178 // and CTCE_Recv will produce a logging for the matching command.
2179 if( ( pDEVBLK->ccwtrace || pDEVBLK->ccwstep ) &&
2180 ( !( IS_CTCE_WAIT( CTCE_Info.actions ) ) ||
2181 !CTCE_Info.sent ) )
2182 {
2183 CTCE_Trace( pDEVBLK, sCount, CTCE_Info.sent ? CTCE_SND : CTCE_LCL,
2184 &CTCE_Info, pDEVBLK->buf, pUnitStat );
2185 }
2186
2187 release_lock( &pDEVBLK->lock );
2188 }
2189
2190 //
2191 // CTCE_Init
2192 //
2193
CTCE_Init(DEVBLK * dev,int argc,char * argv[])2194 static int CTCE_Init( DEVBLK *dev, int argc, char *argv[] )
2195 {
2196 char str[80]; // Thread name
2197 int mtu; // MTU size (binary)
2198 char* listenp; // Listening port number
2199 char* remotep; // Destination port number
2200 char* mtusize; // MTU size (characters)
2201 char* remaddr; // Remote IP address
2202 BYTE c; // Character work area
2203 TID tid; // Thread ID for server
2204 int ctceSmlBin; // Small size (binary)
2205 char* ctceSmlChr; // Small size (characters)
2206 CTCE_PARMBLK parm; // Parameters for the server
2207 CTCE_PARMBLK* arg; // used to pass parameters to the server thread
2208 char address[20]=""; // temp space for IP address
2209 int optval; // Argument for setsockopt
2210
2211 dev->devtype = 0x3088;
2212
2213 dev->ctctype = CTC_CTCE;
2214
2215 // SetSIDInfo( dev, 0x3088, 0x08, 0x0000, 0x00 ); CTCA, Extended Mode
2216 // SetSIDInfo( dev, 0x3088, 0x08, 0x0000, 0x01 ); CTCA, Basic Mode
2217 // SetSIDInfo( dev, 0x3088, 0x1F, 0x0000, 0x00 ); ESCON CTC, Extended Mode, i.e. SCTC
2218 // SetSIDInfo( dev, 0x3088, 0x1F, 0x0000, 0x01 ); ESCON CTC, Basic Mode, i.e. BCTC
2219 // SetSIDInfo( dev, 0x3088, 0x1E, 0x0000, 0x00 ); FICON CTC
2220 // SetSIDInfo( dev, 0x3088, 0x01, ... ); P390 OSA emulation
2221 // SetSIDInfo( dev, 0x3088, 0x60, ... ); OSA/2 adapter
2222 // SetSIDInfo( dev, 0x3088, 0x61, ... ); CISCO 7206 CLAW protocol ESCON connected
2223 // SetSIDInfo( dev, 0x3088, 0x62, ... ); OSA/D device
2224 // But the orignal CTCX_init had this :
2225 SetSIDInfo( dev, 0x3088, 0x08, 0x3088, 0x01 );
2226
2227 dev->numsense = 2;
2228
2229 // A version 4 only feature ...
2230 // dev->excps = 0;
2231
2232 // The halt_device exit is established; in version 4 this is in DEVHND in the ctce_device_hndinfo.
2233 dev->halt_device = &CTCE_Halt;
2234
2235 // Mark both socket file descriptors as not yet connected.
2236 dev->fd = -1;
2237 dev->ctcefd = -1;
2238
2239 // Check for correct number of arguments
2240 if( (argc < 3) && (argc > 5) )
2241 {
2242 logmsg( _("HHCCT055E %04X CTCE: Incorrect number of parameters\n"),
2243 CTCX_DEVNUM( dev ) );
2244 return -1;
2245 }
2246
2247 // The first argument is the listening port number
2248 // which for CTCE must be an even port number.
2249 listenp = *argv++;
2250
2251 if( strlen( listenp ) > 5 ||
2252 sscanf( listenp, "%u%c", &dev->ctce_lport, &c ) != 1 ||
2253 dev->ctce_lport < 1024 || dev->ctce_lport > 65534 )
2254 {
2255 logmsg( _("HHCCT056E %04X CTCE: Invalid port number: %s\n"),
2256 CTCX_DEVNUM( dev ), listenp );
2257 return -1;
2258 }
2259 if( dev->ctce_lport % 2 )
2260 {
2261 logmsg( _("HHCCT057E %04X CTCE: Local port number not even: %s\n"),
2262 CTCX_DEVNUM( dev ), listenp );
2263 return -1;
2264 }
2265
2266 // The second argument is the IP address or hostname of the
2267 // remote side of the point-to-point link
2268 remaddr = *argv++;
2269
2270 if( inet_aton( remaddr, &dev->ctce_ipaddr ) == 0 )
2271 {
2272 struct hostent *hp;
2273
2274 if( ( hp = gethostbyname( remaddr ) ) != NULL )
2275 {
2276 memcpy( &dev->ctce_ipaddr, hp->h_addr, hp->h_length );
2277 strcpy( address, inet_ntoa( dev->ctce_ipaddr ) );
2278 remaddr = address;
2279 }
2280 else
2281 {
2282 logmsg( _("HHCCT058E %04X CTCE: Invalid IP address %s\n"),
2283 CTCX_DEVNUM( dev ), remaddr );
2284 return -1;
2285 }
2286 }
2287
2288 // The third argument is the destination port number
2289 // which for CTCE must be an even port number.
2290 remotep = *argv++;
2291
2292 if( strlen( remotep ) > 5 ||
2293 sscanf( remotep, "%u%c", &dev->ctce_rport, &c ) != 1 ||
2294 dev->ctce_rport < 1024 || dev->ctce_rport > 65534 )
2295 {
2296 logmsg( _("HHCCT059E %04X CTCE: Invalid port number: %s\n"),
2297 CTCX_DEVNUM( dev ), remotep );
2298 return -1;
2299 }
2300 if( dev->ctce_rport % 2 )
2301 {
2302 logmsg( _("HHCCT060E %04X CTCE: Remote port number not even: %s\n"),
2303 CTCX_DEVNUM( dev ), remotep );
2304 return -1;
2305 }
2306
2307 // Enhanced CTC default MTU bufsize is CTCE_MTU_MIN.
2308 if( argc < 4 )
2309 {
2310 mtu = CTCE_MTU_MIN;
2311 }
2312 else
2313 {
2314
2315 // The fourth argument is the maximum transmission unit (MTU) size
2316 mtusize = *argv;
2317
2318 if( strlen( mtusize ) > 5 ||
2319 sscanf( mtusize, "%u%c", &mtu, &c ) != 1 ||
2320 mtu < CTCE_MTU_MIN || mtu > 65536 )
2321 {
2322 logmsg( _("HHCCT061E %04X CTCE: Invalid MTU size %s, allowed range is %d to 65536\n"),
2323 CTCX_DEVNUM( dev ), mtusize, CTCE_MTU_MIN );
2324 return -1;
2325 }
2326 }
2327
2328 // Enhanced CTC only supports an optional 5th parameter,
2329 // the Small MTU size, which defaults to the minimum size
2330 // of the TCP/IP packets exchanged: CTCE_SOKPFX.
2331 ctceSmlBin = sizeof(CTCE_SOKPFX);
2332 if( argc == 5 )
2333 {
2334 ctceSmlChr = *(++argv);
2335
2336 if( strlen( ctceSmlChr ) > 5 ||
2337 sscanf( ctceSmlChr, "%u%c", &ctceSmlBin, &c ) != 1 ||
2338 ctceSmlBin < (int)sizeof(CTCE_SOKPFX) || ctceSmlBin > mtu )
2339 {
2340 ctceSmlBin = sizeof(CTCE_SOKPFX);
2341 logmsg( _("HHCCT062W %04X CTCE: Invalid Small MTU size %s ignored\n"),
2342 CTCX_DEVNUM( dev ), ctceSmlChr );
2343 }
2344 }
2345 dev->ctceSndSml = ctceSmlBin;
2346
2347 // Set the device buffer size equal to the MTU size
2348 dev->bufsize = mtu;
2349
2350 logmsg( _("HHCCT063I %04X CTCE: Awaiting inbound connection :%d <- %s:%d\n"),
2351 CTCX_DEVNUM( dev ), dev->ctce_lport + 1, remaddr, dev->ctce_rport );
2352
2353 // Initialize the file descriptor for the socket connection
2354 parm.listenfd[1] = socket(AF_INET, SOCK_STREAM, 0);
2355 if( parm.listenfd[1] < 0 )
2356 {
2357 logmsg( _("HHCCT064E %04X CTCE: Error creating socket: %s\n"),
2358 CTCX_DEVNUM( dev ), strerror( HSO_errno ) );
2359 CTCX_Close( dev );
2360 return -1;
2361 }
2362
2363 // Allow previous instance of socket to be reused
2364 optval = 1;
2365 setsockopt(parm.listenfd[1], SOL_SOCKET, SO_REUSEADDR,
2366 (GETSET_SOCKOPT_T*)&optval, sizeof(optval));
2367
2368 // set up the listening port
2369 memset( &(parm.addr), 0, sizeof( parm.addr ) );
2370
2371 parm.addr.sin_family = AF_INET;
2372 parm.addr.sin_port = htons(dev->ctce_lport + 1) ;
2373 parm.addr.sin_addr.s_addr = htonl(INADDR_ANY);
2374
2375 if( bind( parm.listenfd[1],
2376 ( struct sockaddr * )&parm.addr,
2377 sizeof( parm.addr ) ) < 0 )
2378 {
2379 logmsg( _("HHCCT065E %04X CTCE: Error binding to socket (port=%d): %s\n"),
2380 CTCX_DEVNUM( dev ), dev->ctce_lport + 1, strerror( HSO_errno ) );
2381 CTCX_Close( dev );
2382 return -1;
2383 }
2384
2385 if( listen( parm.listenfd[1], 1 ) < 0 )
2386 {
2387 logmsg( _("HHCCT066E %04X CTCE: Error on call to listen (port=%d): %s\n"),
2388 CTCX_DEVNUM( dev ), dev->ctce_lport + 1, strerror( HSO_errno ) );
2389 CTCX_Close( dev );
2390 return -1;
2391 }
2392
2393 // we are listening, so create a thread to accept connection
2394 arg = malloc( sizeof( CTCE_PARMBLK ) );
2395 memcpy( arg, &parm, sizeof( parm ) );
2396 arg->dev = dev;
2397 snprintf( str, sizeof( str ), "CTCE %4.4X ListenThread", dev->devnum);
2398 str[sizeof( str )-1]=0;
2399 create_thread( &tid, JOINABLE, CTCE_ListenThread, arg, str );
2400
2401 // for cosmetics, since we are successfully serving,
2402 // fill in some details for the panel.
2403 // Also used for connection verification in CTCE_ListenThread.
2404 // The other side's CTCE device number will be completed
2405 // upon the first receive, we initialize here with dots.
2406 sprintf( dev->filename, ".:....=%s:%d", remaddr, dev->ctce_rport );
2407
2408 // Enhanced CTC adapter intiialization for command register and CB.
2409 dev->ctcexCmd = 0x00;
2410 dev->ctceyCmd = 0x00;
2411 dev->ctceyCmdSCB = 0x00;
2412
2413 // Enhanced CTC adapter sides are state-aware, with initial
2414 // state (1) "Available" and (2) "Not Ready" as in column 6 in
2415 // the table 2.13 in SA22-7203-00, i.e. we consider both
2416 // sides being in state YNR. ALL Flags are cleared.
2417 CLR_CTCE_ALLF( dev->ctcexState );
2418 SET_CTCE_YNR ( dev->ctcexState );
2419 CLR_CTCE_ALLF( dev->ctceyState );
2420 SET_CTCE_YNR ( dev->ctceyState );
2421
2422 // Until we are successfully contacted by the other side,
2423 // we mark the "other side Intervention Required".
2424 dev->sense[0] = SENSE_IR;
2425
2426 // Initialize the 12 bits Send->Recv packet sequence ID with
2427 // bits 13-12 of the CCUU devnum in bits 15-14, and
2428 // bits 01-00 of the CCUU devnum in bits 13-12. This helps
2429 // distinguishing same-host traffic if the Send-Recv side
2430 // CCUU's are sufficiently different (e.g. when under VM).
2431 dev->ctcePktSeq = ((dev->devnum << 2) & 0xC000) |
2432 ((dev->devnum << 12) & 0x3000) ;
2433
2434 // Initialize the CTC lock and condition used to signal
2435 // reception of a command matching the dependent one.
2436 initialize_lock( &dev->ctceEventLock );
2437 initialize_condition( &dev->ctceEvent );
2438
2439 // The ctce_contention_loser side of a CTCE connection will act as
2440 // if a colliding dependent command arrived following the one at
2441 // the other side. The CTC side connecting 1st will reset this,
2442 // and matching SCB commands may alter it also.
2443 dev->ctce_contention_loser = 1;
2444
2445 return 0;
2446 }
2447
2448 //
2449 // CTCE_ListenThread
2450 //
2451
CTCE_ListenThread(void * argp)2452 static void* CTCE_ListenThread( void* argp )
2453 {
2454 int connfd;
2455 socklen_t servlen;
2456 char str[80];
2457 CTCE_PARMBLK parm;
2458 TID tid2; // Thread ID for read thread
2459 int rc; // Return code
2460 #if defined( CTCE_DISABLE_NAGLE )
2461 int optval; // Argument for setsockopt
2462 #endif
2463
2464 // set up the parameters passed via create_thread
2465 parm = *((CTCE_PARMBLK*) argp);
2466 free( argp );
2467
2468 for( ; ; )
2469 {
2470 servlen = sizeof( parm.addr );
2471
2472 // await a connection
2473 connfd = accept( parm.listenfd[1],
2474 (struct sockaddr *)&parm.addr,
2475 &servlen );
2476
2477 sprintf( str, "%s:%d",
2478 inet_ntoa( parm.addr.sin_addr ),
2479 ntohs( parm.addr.sin_port ) );
2480
2481 if( strcmp( str, parm.dev->filename + 7 ) != 0 )
2482 {
2483 logmsg( _("HHCCT067E %04X CTCE: Inconsistent config=%s+%d, connecting client=%s\n"),
2484 CTCX_DEVNUM( parm.dev ), parm.dev->filename + 7, 1, str);
2485 close_socket( connfd );
2486 }
2487 else
2488 {
2489
2490 #if defined( CTCE_DISABLE_NAGLE )
2491 optval = 1;
2492 rc = setsockopt(parm.listenfd[1], IPPROTO_TCP, TCP_NODELAY,
2493 (char*)&optval, sizeof( optval ) );
2494 if( rc < 0 )
2495 {
2496 logmsg( _("HHCCT068E %04X CTCE: TCP_NODELAY error for socket (port %d): %s\n"),
2497 CTCX_DEVNUM( parm.dev ), parm.dev->ctce_lport + 1, strerror( HSO_errno ) );
2498 close_socket( connfd );
2499 }
2500 #endif
2501
2502 // The next odd local port is for reading
2503 parm.dev->ctcefd = connfd;
2504
2505 // This side is ready to start receiving and sending so we
2506 // start a read thread to do the receiving part;
2507 snprintf( str, sizeof(str), "CTCE %04X RecvThread",
2508 parm.dev->devnum );
2509 str[sizeof(str)-1]=0;
2510 rc = create_thread( &tid2, JOINABLE, CTCE_RecvThread, parm.dev, str );
2511 if( rc != 0 )
2512 {
2513 logmsg( _("HHCCT069E %04X CTCE: create_thread error: %s\n"),
2514 CTCX_DEVNUM( parm.dev ), strerror(errno));
2515 }
2516 else
2517 {
2518 logmsg( _("HHCCT070I %04X CTCE: Accepted inbound connection :%d <- %s (bufsize=%d,%d)\n"),
2519 CTCX_DEVNUM( parm.dev ), parm.dev->ctce_lport + 1,
2520 parm.dev->filename + 7, parm.dev->bufsize, parm.dev->ctceSndSml );
2521 }
2522 }
2523
2524 // Ok, so having done that we're going to loop back to the
2525 // accept(). This was meant to handle the connection failing
2526 // at the other end; this end will be ready to accept another
2527 // connection. Although this will happen, I'm sure you can
2528 // see the possibility for bad things to occur (eg if another
2529 // Hercules tries to connect). This will also be fixed RSN.
2530 }
2531
2532 return NULL; // make compiler happy
2533 }
2534
2535 //
2536 // CTCE_Send
2537 //
2538
CTCE_Send(DEVBLK * pDEVBLK,U16 sCount,BYTE * pIOBuf,BYTE * pUnitStat,U16 * pResidual,CTCE_INFO * pCTCE_Info)2539 static void CTCE_Send( DEVBLK* pDEVBLK, U16 sCount,
2540 BYTE* pIOBuf, BYTE* pUnitStat,
2541 U16* pResidual, CTCE_INFO* pCTCE_Info )
2542 {
2543 CTCE_SOKPFX *pSokBuf; // overlay for buf inside DEVBLK
2544 int rc; // Return code
2545
2546 if( ! IS_CTCE_SEND( pCTCE_Info->actions ) )
2547 {
2548 logmsg( _("HHCCT071E %04X CTCE: SEND status incorrectly encoded !\n"),
2549 CTCX_DEVNUM( pDEVBLK ) );
2550 }
2551
2552 // We only ever Send if the sockets are connected.
2553 if( ( pDEVBLK->fd < 0 ) || ( pDEVBLK->ctcefd < 0 ) )
2554 {
2555 logmsg( _("HHCCT072S %04X CTCE: Not all sockets connected: send=%d, receive=%d\n"),
2556 CTCX_DEVNUM( pDEVBLK ), pDEVBLK->fd, pDEVBLK->ctcefd );
2557 *pUnitStat = 0;
2558 return ;
2559 }
2560 pCTCE_Info->sent = 1;
2561
2562 pDEVBLK->ctcexState = CTCE_NEW_X_STATE( pDEVBLK->ctcexCmd );
2563 pDEVBLK->ctce_UnitStat = *pUnitStat;
2564
2565 pSokBuf = (CTCE_SOKPFX*) pDEVBLK->buf;
2566 pSokBuf->CmdReg = pDEVBLK->ctcexCmd;
2567 pSokBuf->FsmSta = pDEVBLK->ctcexState;
2568 pSokBuf->sCount = sCount;
2569 pSokBuf->PktSeq = ++pDEVBLK->ctcePktSeq;
2570 pSokBuf->SndLen = pDEVBLK->ctceSndSml;
2571 pSokBuf->DevNum = pDEVBLK->devnum;
2572 pSokBuf->ssid = pDEVBLK->ssid;
2573
2574 // Only a (non-WEOF) write command data includes sending the IOBuf.
2575 if( IS_CTCE_CCW_WRT( pDEVBLK->ctcexCmd ) )
2576 {
2577 memcpy( pDEVBLK->buf + sizeof(CTCE_SOKPFX), pIOBuf, sCount );
2578
2579 // Increase the SndLen if the sCount is too large.
2580 if( pSokBuf->SndLen < ( sCount + sizeof(CTCE_SOKPFX) ) )
2581 pSokBuf->SndLen = ( sCount + sizeof(CTCE_SOKPFX) );
2582
2583 // Write Data.
2584 if( pDEVBLK->ccwstep )
2585 packet_trace( pIOBuf, sCount );
2586
2587 // If bufsize (init from the MTU parameter) is not large enough
2588 // then we will have a severe error as the CTC will not connect.
2589 if( pDEVBLK->bufsize < pSokBuf->SndLen )
2590 {
2591 logmsg( _("HHCCT073S %04X CTCE: bufsize parameter %d is too small; increase at least to %d\n"),
2592 CTCX_DEVNUM( pDEVBLK ), pDEVBLK->bufsize, pSokBuf->SndLen );
2593 }
2594 }
2595 pCTCE_Info->sok_buf_len = pSokBuf->SndLen;
2596
2597 // Write all of this to the other (y-)side.
2598 rc = write_socket( pDEVBLK->fd, pDEVBLK->buf, pSokBuf->SndLen );
2599
2600 if( rc < 0 )
2601 {
2602 logmsg( _("HHCCT074E %04X CTCE: Error writing to %s: %s\n"),
2603 CTCX_DEVNUM( pDEVBLK ), CTCE_FILENAME, strerror( HSO_errno ) );
2604
2605 pDEVBLK->sense[0] = SENSE_EC;
2606 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
2607
2608 // For lack of anything better, we return to the not ready state.
2609 CLR_CTCE_ALLF(pDEVBLK->ctcexState);
2610 SET_CTCE_YNR(pDEVBLK->ctcexState);
2611 return;
2612 }
2613
2614 // If this command is a matching one for the other (y-)side
2615 // Working(D) state, then that (y-)side becomes available.
2616 if IS_CTCE_MATCH( pCTCE_Info->actions )
2617 {
2618 SET_CTCE_YAV( pDEVBLK->ctceyState );
2619 }
2620
2621 // If we received a command that is going to put our (x-)side
2622 // in a Working(D) state, then we will need to wait until a
2623 // matching command arrives from the other (y-)side. The WAIT
2624 // timeout is chosen to be long enough to not timeout over periods
2625 // if inactivity; we experienced up to 6 secs, so we set it to 60.
2626 if( IS_CTCE_WAIT( pCTCE_Info->actions ) )
2627 {
2628
2629 // Produce a CTCE Trace logging if requested.
2630 if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep )
2631 {
2632 CTCE_Trace( pDEVBLK, sCount, CTCE_SND, pCTCE_Info, pDEVBLK->buf, pUnitStat );
2633 }
2634
2635 obtain_lock( &pDEVBLK->ctceEventLock );
2636 release_lock( &pDEVBLK->lock );
2637
2638 pCTCE_Info->wait_rc = timed_wait_condition_relative_usecs(
2639 &pDEVBLK->ctceEvent,
2640 &pDEVBLK->ctceEventLock,
2641 60000000,
2642 NULL );
2643
2644 obtain_lock( &pDEVBLK->lock );
2645 release_lock( &pDEVBLK->ctceEventLock );
2646
2647 // First we check for Halt or Clear Subchannel
2648 if( pCTCE_Info->wait_rc == ETIMEDOUT || pCTCE_Info->wait_rc == EINTR )
2649 {
2650 // check for halt condition
2651 if( pDEVBLK->scsw.flag2 & SCSW2_FC_HALT ||
2652 pDEVBLK->scsw.flag2 & SCSW2_FC_CLEAR )
2653 {
2654 if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep )
2655 {
2656 logmsg( _("HHCCT075I %04X CTCE: Halt or Clear Recognized\n"),
2657 CTCX_DEVNUM( pDEVBLK ) );
2658 }
2659
2660 //??? *pUnitStat = CSW_CE | CSW_DE;
2661 *pUnitStat = 0;
2662 *pResidual = sCount;
2663 }
2664
2665 // Other timeouts or errors should not occur.
2666 // But if they do, we try to recover as if the other side
2667 // was in a working(D) state.
2668 else
2669 {
2670 *pUnitStat = CSW_BUSY | CSW_ATTN ;
2671 SET_CTCE_YAV( pDEVBLK->ctcexState );
2672 }
2673
2674 // Produce a trace logging if requested.
2675 if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep )
2676 {
2677 CTCE_Trace( pDEVBLK, sCount, CTCE_SND, pCTCE_Info, pDEVBLK->buf, pUnitStat );
2678 }
2679 return;
2680 }
2681
2682 // Trace the non-zero WAIT RC (e.g. timeout, RC=138 (windows) or 110 (unix)).
2683 else if( pCTCE_Info->wait_rc != 0 )
2684 {
2685 CTCE_Trace( pDEVBLK, sCount, CTCE_SND, pCTCE_Info, pDEVBLK->buf, pUnitStat );
2686 }
2687
2688 // A WRITE EOF command from the other side will have resulted
2689 // in the WEOF flag being set. If this was a matching command
2690 // for a READ then unit exception needs to be included.
2691 else if( IS_CTCE_WEOF( pDEVBLK->ctcexState ) &&
2692 IS_CTCE_CCW_RDA( pDEVBLK->ctcexCmd ) )
2693 {
2694 *pResidual = 0;
2695 *pUnitStat = CSW_CE | CSW_DE | CSW_UX;
2696
2697 // Produce a trace logging if requested.
2698 if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep )
2699 {
2700 CTCE_Trace( pDEVBLK, sCount, CTCE_SND, pCTCE_Info, pDEVBLK->buf, pUnitStat );
2701 }
2702 return;
2703 }
2704 } // if( IS_CTCE_WAIT( pCTCE_Info->actions ) )
2705
2706 // In the non-WAIT case the final UnitStat is always
2707 // CE + DE provided the y-state is not Not_Ready.
2708 else if( !IS_CTCE_YNR( pDEVBLK -> ctceyState ) )
2709 {
2710 pDEVBLK->ctce_UnitStat = CSW_CE | CSW_DE;
2711 }
2712
2713 // If the command (by now matched) was a CONTROL command, then this
2714 // side become the contention loser.
2715 if( IS_CTCE_CCW_CTL( pDEVBLK->ctcexCmd ) )
2716 {
2717 pDEVBLK->ctce_contention_loser = 1;
2718 }
2719
2720 // Command collisions never return data.
2721 if( pDEVBLK->ctce_UnitStat == (CSW_BUSY | CSW_ATTN) )
2722 {
2723 *pResidual = sCount;
2724 }
2725
2726 // If the command (by now matched) was a READ command, then the
2727 // other (y-)side data is available in the DEVBLK buf, so we
2728 // can copy it into the IO channel buffer and compute residual.
2729 else if( IS_CTCE_CCW_RED( pDEVBLK->ctcexCmd ) )
2730 {
2731
2732 // The actual length of data transferred is the minimum of
2733 // the current READ sCount, and the original WRITE sCount
2734 // which is recorded immediately following the CTCE_SOKPFX.
2735 pSokBuf->sCount =
2736 ( sCount <= *(U16*)( pDEVBLK->buf + sizeof(CTCE_SOKPFX) ) )
2737 ? sCount : *(U16*)( pDEVBLK->buf + sizeof(CTCE_SOKPFX) );
2738
2739 // Immediately followed by the WRITE data previously received.
2740 memcpy( pIOBuf, pDEVBLK->buf + sizeof(CTCE_SOKPFX) + sizeof(pSokBuf->sCount),
2741 pSokBuf->sCount ) ;
2742 *pResidual = sCount - pSokBuf->sCount;
2743 }
2744 else
2745 {
2746 *pResidual = 0;
2747 }
2748
2749 // The final UnitStat may have been amended by CTCE_Recv like when
2750 // it received a matching command (typically resulting in CE + DE).
2751 // We need to merge this.
2752 *pUnitStat |= pDEVBLK->ctce_UnitStat;
2753 pDEVBLK->ctce_UnitStat = 0;
2754
2755 return;
2756 }
2757
2758 //
2759 // CTCE_RecvThread
2760 //
2761
CTCE_RecvThread(void * argp)2762 static void* CTCE_RecvThread( void* argp )
2763 {
2764 DEVBLK *pDEVBLK = (DEVBLK*) argp; // device block pointer
2765 CTCE_SOKPFX *pSokBuf; // overlay for buf inside DEVBLK
2766 CTCE_INFO CTCE_Info; // CTCE information (also for tracing)
2767 int iLength = 0;
2768 BYTE *buf; //-> Device recv data buffer
2769 U64 ctcePktCnt = 0; // Recvd Packet Count
2770 U64 ctceBytCnt = 0; // Recvd Byte Count
2771 BYTE ctce_recv_mods_UnitStat; // UnitStat modifications
2772 int i = 0; // temporary variable
2773
2774 // When the receiver thread is (re-)started, the CTCE devblk is (re-)initialized
2775 obtain_lock( &pDEVBLK->lock );
2776
2777 // Enhanced CTC adapter intiialization for command register and CB
2778 pDEVBLK->ctcexCmd = 0x00;
2779 pDEVBLK->ctceyCmd = 0x00;
2780 pDEVBLK->ctceyCmdSCB = 0x00;
2781
2782 // CTCE DEVBLK (re-)initialisation completed.
2783 release_lock( &pDEVBLK->lock );
2784
2785 // Avoid having to lock the DEVBLK whilst awaiting data to arrive via read_socket
2786 buf = malloc( pDEVBLK->bufsize );
2787 pSokBuf = (CTCE_SOKPFX*)buf;
2788
2789 // Initialise our CTCE_Info as needed.
2790 CTCE_Info.de_ready_attn_rc = 0;
2791 CTCE_Info.working_attn_rc = 0;
2792 CTCE_Info.busy_waits = 0;
2793
2794 // This thread will loop until we receive a zero-length packet caused by CTCX_close from the other side.
2795 for( ; ; )
2796 {
2797 // We read whatever the other (y-)side of the CTC has sent us,
2798 // which by now won't block until the complete bufsize is received.
2799 iLength = read_socket( pDEVBLK->ctcefd, buf, pDEVBLK->ctceSndSml );
2800
2801 // Followed by the receiving the rest if the default SndLen was too small.
2802 if( ( pDEVBLK->ctceSndSml < pSokBuf->SndLen ) && ( iLength != 0 ) )
2803 iLength += read_socket( pDEVBLK->ctcefd, buf + pDEVBLK->ctceSndSml,
2804 pSokBuf->SndLen - pDEVBLK->ctceSndSml );
2805
2806 // In case we are closing down this thread can end.
2807 if( iLength == 0 )
2808 {
2809
2810 // We report some statistics.
2811 logmsg( _("HHCCT076I %04X CTCE: Connection closed; %lld MB received in %lld packets from %s\n"),
2812 CTCX_DEVNUM( pDEVBLK ), ctceBytCnt / 1048576 , ctcePktCnt, CTCE_FILENAME );
2813
2814 // And this receiver socket can now be closed.
2815 close_socket( pDEVBLK->ctcefd );
2816 pDEVBLK->ctcefd = -1;
2817
2818 free( buf );
2819 return NULL; // make compiler happy
2820 }
2821
2822 // Changes to DEVBLK must be lock protected as other threads might update as well.
2823 obtain_lock(&pDEVBLK->lock);
2824
2825 // Check for other error condition
2826 if( iLength < 0 )
2827 {
2828 logmsg( _("HHCCT077E %04X CTCE: Error reading from %s: %s\n"),
2829 CTCX_DEVNUM( pDEVBLK ), CTCE_FILENAME, strerror ( HSO_errno ) );
2830 pDEVBLK->sense[0] = SENSE_EC;
2831 pDEVBLK->scsw.unitstat = CSW_CE | CSW_DE | CSW_UC;
2832 }
2833 else
2834 {
2835
2836 // Upon the first recv we will fill out the devnum in the filename.
2837 if( pDEVBLK->filename[2] == '.' )
2838 {
2839 snprintf( pDEVBLK->filename, 7, "%1d:%04X",
2840 SSID_TO_LCSS( pSokBuf->ssid ), pSokBuf->DevNum );
2841 pDEVBLK->filename[6] = '=';
2842 }
2843
2844 // Update the Receive statistics counters.
2845 ctcePktCnt += 1 ;
2846 ctceBytCnt += iLength ;
2847
2848 // Initialise the UnitStat modifications.
2849 ctce_recv_mods_UnitStat = 0;
2850
2851 // Save the previous CTCE states,
2852 // our (x-)side as well as the other (y-)side.
2853 CTCE_Info.state_x_prev = pDEVBLK->ctcexState;
2854 CTCE_Info.state_y_prev = pDEVBLK->ctceyState;
2855
2856 // Set extended mode from the other side also applies to this side.
2857 if( IS_CTCE_CCW_SEM( pDEVBLK->ctceyCmd ) )
2858 {
2859 pDEVBLK->ctcxmode = 1;
2860 }
2861
2862 // The command received from the other (y-)side may cause a
2863 // state transition on our (x-)side, as well as some actions.
2864 // Both depend on our current (x-)side state and are encoded
2865 // within the FSM table.
2866 CTCE_Info.state_new = CTCE_NEW_Y_STATE( pSokBuf->CmdReg );
2867 CTCE_Info.actions = CTCE_Fsm[CTCE_CMD( pSokBuf->CmdReg )]
2868 [CTCE_Y_STATE_FSM_IDX].actions;
2869 CTCE_Info.x_unit_stat = CTCE_Fsm[CTCE_CMD( pSokBuf->CmdReg )]
2870 [CTCE_Y_STATE_FSM_IDX].x_unit_stat;
2871 CTCE_Info.con_lost = 0;
2872 CTCE_Info.con_won = 0;
2873
2874 // Command collision occurs when both sides receive a
2875 // (non-matching) DEPendent command at the same time,
2876 // crossing each other in xfer to the other side (e.g. two
2877 // READ or WRITE commands). Both sides would respond with
2878 // a Busy+Attention device status.
2879 if( ( CTCE_Info.x_unit_stat == ( CSW_BUSY | CSW_ATTN ) )
2880 && IS_CTCE_CCW_DEP( pSokBuf->CmdReg ) )
2881 {
2882
2883 // In a real CTC this never occurs, there is always a
2884 // first and a second side. CTCE emulates the second
2885 // side behaviour where ctce_contention_loser==1.
2886 if( pDEVBLK->ctce_contention_loser )
2887 {
2888
2889 // This is done by signaling this by now awaiting
2890 // side as if a matching command was received, but
2891 // only after re-instating the original FSM state
2892 // and ensuring that the required Busy+Attention
2893 // device status will bereturned. Effectively,
2894 // this is a contention lost situation.
2895 CTCE_Info.con_lost = 1;
2896 pDEVBLK->ctcexState = CTCE_Info.state_new;
2897 pDEVBLK->ctce_UnitStat = CSW_BUSY | CSW_ATTN;
2898 obtain_lock( &pDEVBLK->ctceEventLock );
2899 signal_condition( &pDEVBLK->ctceEvent );
2900 release_lock( &pDEVBLK->ctceEventLock );
2901
2902 // After our (x-)state is reset, we need to
2903 // re-compute the FSM state transition effects.
2904 CTCE_Info.state_new = CTCE_NEW_Y_STATE( pSokBuf->CmdReg );
2905 CTCE_Info.actions = CTCE_Fsm[CTCE_CMD( pSokBuf->CmdReg )]
2906 [CTCE_Y_STATE_FSM_IDX].actions;
2907 }
2908
2909 // At the contention winning side, we can simply ignore
2910 // the CTCE_Recv, as the losing side will effectively
2911 // behave is if it never happened.
2912 else
2913 {
2914 CTCE_Info.con_won = 1;
2915 }
2916 }
2917 if( CTCE_Info.con_won != 1 )
2918 {
2919
2920 // Device-End status indicating ready will be presented
2921 // if the y-side has just now become ready.
2922 CTCE_Info.de_ready = ( IS_CTCE_YNR( pDEVBLK->ctceyState ) &&
2923 !IS_CTCE_YNR( pSokBuf->FsmSta ) ) ? 1 : 0;
2924
2925 // Our (x-)side knowledge from the other (y-)side is updated.
2926 pDEVBLK->ctceyState = pSokBuf->FsmSta;
2927 pDEVBLK->ctceyCmd = pSokBuf->CmdReg;
2928 pDEVBLK->ctceyCmdSCB = pSokBuf->CmdReg;
2929
2930 // Only if the other (y-)side sent us a write command will
2931 // we copy the socket buffer into the device buffer.
2932 if( IS_CTCE_CCW_WRT( pDEVBLK->ctceyCmd ) )
2933 {
2934
2935 // We retain the sCount of this WRITE command for later
2936 // comparison against the matching READ command, ahead
2937 // of the data itself following CTCE_SOKPFX.
2938 *(U16*)( pDEVBLK->buf + sizeof(CTCE_SOKPFX) ) = pSokBuf->sCount ;
2939
2940 memcpy( pDEVBLK->buf + sizeof(CTCE_SOKPFX) + sizeof(pSokBuf->sCount) ,
2941 buf + sizeof(CTCE_SOKPFX), pSokBuf->sCount );
2942 }
2943
2944 // If the other side sent us a WRITE EOF command
2945 // then we just set the WEOF flag on our side.
2946 else if( IS_CTCE_CCW_WEF( pDEVBLK->ctceyCmd ) )
2947 {
2948 SET_CTCE_WEOF( pDEVBLK->ctcexState );
2949 }
2950
2951 // If the other side sent us a READ or READBK command whilst the
2952 // previous command at our (x-) side was a WRITE EOF command then
2953 // the other side will have generated a Unit Exception to the WEOF
2954 // setting, effectively discarding that READ command. We therefore
2955 // ignore this READ command, but we need to set the resulting
2956 // state to Available. We clear the Wait + Attention actions.
2957 else if( IS_CTCE_CCW_RDA( pDEVBLK->ctceyCmd ) &&
2958 IS_CTCE_CCW_WEF( pDEVBLK->ctcexCmd ) &&
2959 IS_CTCE_ATTN( CTCE_Info.actions ) )
2960 {
2961 SET_CTCE_YAV( pDEVBLK->ctceyState );
2962 CLR_CTCE_WAIT( CTCE_Info.actions );
2963 CLR_CTCE_ATTN( CTCE_Info.actions );
2964 }
2965
2966 // If the other (y-)side sent us a matching command for our
2967 // (x-)side Working(D) state, then we need to signal that
2968 // condition so that CTCE_Send no longer needs to wait.
2969 if( IS_CTCE_MATCH( CTCE_Info.actions ) )
2970 {
2971 obtain_lock( &pDEVBLK->ctceEventLock );
2972 signal_condition( &pDEVBLK->ctceEvent );
2973 release_lock( &pDEVBLK->ctceEventLock );
2974
2975 // Both sides return to the available state.
2976 SET_CTCE_YAV( pDEVBLK->ctcexState );
2977 SET_CTCE_YAV( pDEVBLK->ctceyState );
2978
2979 // All matching commands result in a final UnitStat
2980 // CE + DE stat at the local device end.
2981 ctce_recv_mods_UnitStat = CSW_CE | CSW_DE;
2982 } // if( IS_CTCE_MATCH( CTCE_Info.actions ) )
2983
2984 // If the other (y-)side sent us a Device-End status
2985 // indicating Ready then this has to be presented on this side.
2986 else if( CTCE_Info.de_ready )
2987 {
2988 release_lock( &pDEVBLK->lock );
2989 ctce_recv_mods_UnitStat = CSW_DE;
2990 CTCE_Info.de_ready_attn_rc = device_attention( pDEVBLK, CSW_DE );
2991 obtain_lock( &pDEVBLK->lock );
2992
2993 // Reset sense byte 0 bits 1 and 7.
2994 pDEVBLK->sense[0] &= ~( SENSE_IR | SENSE_OC );
2995
2996 }
2997
2998 // If the other (y-)side sent us a command that may require
2999 // us to signal attention then we will do so provided no
3000 // program chain is in progress (SA22-7203-00, item 2.1.1,
3001 // second paragraph). We test for that condition using the
3002 // Command Chaining flag on the last received CCW.
3003 CTCE_Info.attn_can = 0;
3004 if( IS_CTCE_ATTN( CTCE_Info.actions )
3005 && ( !pDEVBLK->ctce_ccw_flags_cc )
3006 && ( CTCE_Info.con_lost == 0 ) )
3007 {
3008
3009 // Produce a CTCE Trace logging if requested.
3010 if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep )
3011 {
3012
3013 // Disable ATTN RC reporting this time.
3014 CTCE_Info.working_attn_rc = -1;
3015
3016 // In a contention winner situation, the command
3017 // received from the other (y-)side still needs
3018 // to be reported correctly.
3019 pDEVBLK->ctceyCmd = pSokBuf->CmdReg;
3020 CTCE_Info.sok_buf_len = iLength;
3021 CTCE_Trace( pDEVBLK, pSokBuf->sCount, CTCE_RCV, &CTCE_Info, buf, &ctce_recv_mods_UnitStat );
3022 }
3023
3024 // The device_attention might not work on the first
3025 // attempt due to the fact that we need to release
3026 // the device lock around it, merely because that
3027 // routine obtains and releases the device lock.
3028 // During that short period, one or more commands
3029 // may have come in between, causing a device busy
3030 // and a possible other (y-)side status update. So
3031 // we may need to re-try the ATTN if needed at all.
3032 release_lock( &pDEVBLK->lock );
3033 CTCE_Info.working_attn_rc = 1;
3034 for( CTCE_Info.busy_waits = 0;
3035 ( CTCE_Info.working_attn_rc == 1 ) &&
3036 ( CTCE_Info.attn_can == 0 ) &&
3037 ( CTCE_Info.busy_waits <= 20 ) ;
3038 CTCE_Info.busy_waits++ )
3039 {
3040 CTCE_Info.working_attn_rc = device_attention( pDEVBLK, CSW_ATTN );
3041
3042 // ATTN RC=1 means a device busy status did
3043 // appear so that the signal did not work.
3044 // We will retry after some (increasingly)
3045 // small amount of time.
3046 if( CTCE_Info.working_attn_rc == 1 )
3047 {
3048 if( CTCE_Info.busy_waits == 0 )
3049 {
3050 i = 10;
3051 }
3052 else
3053 {
3054 i = i * 2;
3055 }
3056 usleep(i);
3057
3058 // Cancel the ATTN in case a CCW program
3059 // has started in the mean time.
3060 if ( pDEVBLK->ctce_ccw_flags_cc )
3061 {
3062 CTCE_Info.attn_can = 1;
3063 }
3064 }
3065 }
3066 obtain_lock( &pDEVBLK->lock );
3067
3068 // We will show the ATTN status if it was signalled.
3069 if( CTCE_Info.working_attn_rc == 0 )
3070 {
3071 ctce_recv_mods_UnitStat = CSW_ATTN;
3072 }
3073 CTCE_Info.busy_waits -= 1;
3074 } // if( IS_CTCE_ATTN( CTCE_Info.actions ) && ... /* Attention Needed */
3075 else if( IS_CTCE_ATTN( CTCE_Info.actions ) )
3076 {
3077 CTCE_Info.busy_waits = 0;
3078 CTCE_Info.attn_can = 1;
3079 }
3080 }
3081
3082 // Merge any UnitStat modifications into the final one.
3083 pDEVBLK->ctce_UnitStat |= ctce_recv_mods_UnitStat;
3084
3085 // Produce a CTCE Trace logging if requested.
3086 if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep
3087 || ( ctce_recv_mods_UnitStat == ( CSW_BUSY | CSW_ATTN ) )
3088 || ( CTCE_Info.de_ready_attn_rc != 0 )
3089 || ( ( CTCE_Info.working_attn_rc != 0 ) && ( CTCE_Info.attn_can == 0 ) )
3090 || ( CTCE_Info.busy_waits >= 3 ) )
3091 {
3092
3093 // In a contention winner situation, the command
3094 // received from the other (y-)side still needs
3095 // to be reported correctly.
3096 pDEVBLK->ctceyCmd = pSokBuf->CmdReg;
3097
3098 if( ctce_recv_mods_UnitStat != 0 )
3099 {
3100 ctce_recv_mods_UnitStat = pDEVBLK->ctce_UnitStat;
3101 }
3102 CTCE_Info.sok_buf_len = iLength;
3103 CTCE_Trace( pDEVBLK, pSokBuf->sCount, CTCE_RCV, &CTCE_Info, buf, &ctce_recv_mods_UnitStat );
3104 }
3105 CTCE_Info.de_ready_attn_rc = 0;
3106 CTCE_Info.working_attn_rc = 0;
3107 CTCE_Info.busy_waits = 0;
3108 }
3109
3110 release_lock( &pDEVBLK->lock );
3111 }
3112 }
3113
3114 //
3115 // CTCE_Halt -- Halt device for CTCE adapter
3116 //
3117
CTCE_Halt(DEVBLK * pDEVBLK)3118 static void CTCE_Halt( DEVBLK* pDEVBLK )
3119 {
3120
3121 // obtain_lock( &pDEVBLK->lock ) already carried out by caller in channel.c
3122 if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep )
3123 {
3124 logmsg( _("HHCCT078I %04X CTCE: -| Halt x=%s y=%s\n"),
3125 CTCX_DEVNUM( pDEVBLK ),
3126 CTCE_StaStr[pDEVBLK->ctcexState & 0x07],
3127 CTCE_StaStr[pDEVBLK->ctceyState & 0x07] );
3128 }
3129
3130 // Halt device for a CTCE device is a selective reset,
3131 // requiring our (x-)side to cancel any Working(D) wait state
3132 // if needed, and to return to the not ready state.
3133 if( IS_CTCE_YWK( pDEVBLK->ctcexState ) )
3134 {
3135 obtain_lock( &pDEVBLK->ctceEventLock );
3136 signal_condition( &pDEVBLK->ctceEvent );
3137 release_lock( &pDEVBLK->ctceEventLock );
3138 CLR_CTCE_ALLF(pDEVBLK->ctcexState);
3139 SET_CTCE_YNR(pDEVBLK->ctcexState);
3140 }
3141 }
3142
3143 // ====================================================================
3144 // Support Functions
3145 // ====================================================================
3146
3147 // ---------------------------------------------------------------------
3148 // ParseMAC
3149 // ---------------------------------------------------------------------
3150 //
3151 // Parse a string containing a MAC (hardware) address and return the
3152 // binary equivalent.
3153 //
3154 // Input:
3155 // pszMACAddr Pointer to string containing a MAC Address in the
3156 // format "xx-xx-xx-xx-xx-xx" or "xx:xx:xx:xx:xx:xx".
3157 //
3158 // Output:
3159 // pbMACAddr Pointer to a BYTE array to receive the MAC Address
3160 // that MUST be at least sizeof(MAC) bytes long.
3161 //
3162 // Returns:
3163 // 0 on success, -1 otherwise
3164 //
3165
ParseMAC(char * pszMACAddr,BYTE * pbMACAddr)3166 int ParseMAC( char* pszMACAddr, BYTE* pbMACAddr )
3167 {
3168 char work[((sizeof(MAC)*3)-0)];
3169 BYTE sep;
3170 int x;
3171 unsigned i;
3172
3173 if (strlen(pszMACAddr) != ((sizeof(MAC)*3)-1)
3174 || (sizeof(MAC) > 1 &&
3175 *(pszMACAddr+2) != '-' &&
3176 *(pszMACAddr+2) != ':')
3177 )
3178 {
3179 errno = EINVAL;
3180 return -1;
3181 }
3182
3183 strncpy(work,pszMACAddr,((sizeof(MAC)*3)-1));
3184 work[((sizeof(MAC)*3)-1)] = sep = *(pszMACAddr+2);
3185
3186 for (i=0; i < sizeof(MAC); i++)
3187 {
3188 if
3189 (0
3190 || !isxdigit(work[(i*3)+0])
3191 || !isxdigit(work[(i*3)+1])
3192 || sep != work[(i*3)+2]
3193 )
3194 {
3195 errno = EINVAL;
3196 return -1;
3197 }
3198
3199 work[(i*3)+2] = 0;
3200 sscanf(&work[(i*3)+0],"%x",&x);
3201 *(pbMACAddr+i) = x;
3202 }
3203
3204 return 0;
3205 }
3206
3207 // ---------------------------------------------------------------------
3208 // packet_trace
3209 // ---------------------------------------------------------------------
3210 //
3211 // Subroutine to trace the contents of a buffer
3212 //
3213
packet_trace(BYTE * pAddr,int iLen)3214 void packet_trace( BYTE* pAddr, int iLen )
3215 {
3216 int offset;
3217 unsigned int i;
3218 unsigned char c = '\0';
3219 unsigned char e = '\0';
3220 unsigned char print_chars[17];
3221
3222 for( offset = 0; offset < iLen; )
3223 {
3224 memset( print_chars, 0, sizeof( print_chars ) );
3225
3226 logmsg( "+%4.4X ", offset );
3227
3228 for( i = 0; i < 16; i++ )
3229 {
3230 c = *pAddr++;
3231
3232 if( offset < iLen )
3233 {
3234 logmsg("%2.2X", c);
3235
3236 print_chars[i] = '.';
3237 e = guest_to_host( c );
3238
3239 if( isprint( e ) )
3240 print_chars[i] = e;
3241 if( isprint( c ) )
3242 print_chars[i] = c;
3243 }
3244 else
3245 {
3246 logmsg( " " );
3247 }
3248
3249 offset++;
3250 if( ( offset & 3 ) == 0 )
3251 {
3252 logmsg( " " );
3253 }
3254 }
3255
3256 logmsg( " %s\n", print_chars );
3257 }
3258 }
3259
3260 // ---------------------------------------------------------------------
3261 // CTCE_ChkSum
3262 // ---------------------------------------------------------------------
3263 //
3264 // Subroutine to compute a XOR-based checksum for use in debug messages.
3265 //
3266
CTCE_ChkSum(const BYTE * pBuf,const U16 BufLen)3267 U32 CTCE_ChkSum(const BYTE* pBuf, const U16 BufLen)
3268 {
3269 U32 i;
3270 U32 XORChk = 0; // XOR of buffer for checking
3271 BYTE *pXOR = (BYTE*)&XORChk; // -> XORChk
3272
3273
3274 // We initialize the result with the buffer length so that
3275 // different length zero buffers yield a different checksum.
3276 XORChk = BufLen;
3277 for(i = 0; i < BufLen; i++)
3278 {
3279 if( (i % 4) == 0 )
3280 {
3281 pXOR = (BYTE*)&XORChk;
3282 }
3283 *pXOR++ ^= *pBuf++;
3284 }
3285 return XORChk;
3286 }
3287
3288 // ---------------------------------------------------------------------
3289 // CTCE_Trace
3290 // ---------------------------------------------------------------------
3291 //
3292 // Subroutine to produce a CTCE trace logging when requested.
3293 //
3294
CTCE_Trace(const DEVBLK * pDEVBLK,const U16 sCount,const enum CTCE_Cmd_Xfr eCTCE_Cmd_Xfr,const CTCE_INFO * pCTCE_Info,const BYTE * pCTCE_Buf,const BYTE * pUnitStat)3295 void CTCE_Trace( const DEVBLK* pDEVBLK,
3296 const U16 sCount,
3297 const enum CTCE_Cmd_Xfr eCTCE_Cmd_Xfr,
3298 const CTCE_INFO* pCTCE_Info,
3299 const BYTE* pCTCE_Buf,
3300 const BYTE* pUnitStat )
3301 {
3302 static char *CTCE_XfrStr[3] = {
3303 "-|" , // 0 = CTCE_LCL
3304 "->" , // 1 = CTCE_SND
3305 "<-" // 2 = CTCE_RCV
3306 };
3307 BYTE ctce_Cmd; // CTCE command being traced
3308 BYTE ctce_PktSeq; // Packet Sequence number traced
3309 CTCE_SOKPFX *pSokBuf; // overlay for buf inside DEVBLK
3310 BYTE ctce_state_verify; // CTCE state to be verfified
3311 char ctce_state_l_xy[2]; // CTCE X+Y states, left
3312 char ctce_state_r_xy[2]; // CTCE X+Y stares, right
3313 char ctce_trace_stat[16]; // to contain " Stat=.. CC=."
3314 char ctce_trace_xtra[256]; // to contain extra info when tracing
3315 char ctce_trace_xtra_temp[256]; // temporary work area for the above
3316
3317 pSokBuf = (CTCE_SOKPFX*)pCTCE_Buf;
3318
3319 // Report on the device status and CCW Command Chaining flag.
3320 if( ( eCTCE_Cmd_Xfr != CTCE_RCV ) || ( *pUnitStat != 0 ) ||
3321 ( IS_CTCE_MATCH( pCTCE_Info->actions ) ) )
3322 {
3323 snprintf( ctce_trace_stat, sizeof( ctce_trace_stat ),
3324 "Stat=%02X CC=%d", *pUnitStat, pDEVBLK->ctce_ccw_flags_cc );
3325 }
3326 else
3327 {
3328 snprintf( ctce_trace_stat, sizeof( ctce_trace_stat ),
3329 " CC=%d", pDEVBLK->ctce_ccw_flags_cc );
3330 }
3331
3332 ctce_trace_xtra[0] = '\0' ;
3333
3334 // The other side's entering a "Working" state may
3335 // require an Attention or not, which will be shown.
3336 // Please note that the CTCE_ACTIONS_PRT macro in
3337 // that case will show "ATTN" at the rightmost end.
3338 if( IS_CTCE_ATTN( pCTCE_Info->actions ) && ( eCTCE_Cmd_Xfr == CTCE_RCV ) )
3339 {
3340 if( pCTCE_Info->attn_can )
3341 {
3342 strlcat( ctce_trace_xtra, "->NONE", sizeof( ctce_trace_xtra ) );
3343 }
3344 else if( pCTCE_Info->working_attn_rc > -1 )
3345 {
3346 snprintf( ctce_trace_xtra_temp, sizeof( ctce_trace_xtra_temp ),
3347 "->RC=%d", pCTCE_Info->working_attn_rc );
3348 strlcat( ctce_trace_xtra, ctce_trace_xtra_temp, sizeof( ctce_trace_xtra ) );
3349 }
3350 }
3351
3352 // The other side's "DE Ready" signalling to be shown.
3353 if( pCTCE_Info->de_ready )
3354 {
3355 snprintf( ctce_trace_xtra_temp, sizeof( ctce_trace_xtra_temp ),
3356 " DE_READY->RC=%d",pCTCE_Info->de_ready_attn_rc );
3357 strlcat( ctce_trace_xtra, ctce_trace_xtra_temp, sizeof( ctce_trace_xtra ) );
3358 }
3359
3360 // "WEOF" means that the "Write End of File" bit is or was set.
3361 // "WEOF->SET" means it just got set right now, in which case
3362 // "WEOF->SET->UX" means an Unit Exception (UX) will follow because
3363 // it got set because of a WEOF command matching a Read command
3364 // (which actually will clear the WEOF immediately thereafter).
3365 // "WEOF->CLR" indicates the WEOF bit just got reset.
3366 if( IS_CTCE_WEOF( pCTCE_Info->state_x_prev ) ||
3367 IS_CTCE_WEOF( pDEVBLK->ctcexState ) )
3368 {
3369 strlcat( ctce_trace_xtra, " WEOF", sizeof( ctce_trace_xtra ) );
3370 }
3371 if( !IS_CTCE_WEOF( pCTCE_Info->state_x_prev ) &&
3372 IS_CTCE_WEOF( pDEVBLK->ctcexState ) )
3373 {
3374 strlcat( ctce_trace_xtra, "->SET", sizeof( ctce_trace_xtra ) );
3375 if( IS_CTCE_MATCH( pCTCE_Info->actions ) )
3376 {
3377 strlcat( ctce_trace_xtra, "->UX", sizeof( ctce_trace_xtra ) );
3378 }
3379 }
3380 if( IS_CTCE_WEOF( pCTCE_Info->state_x_prev ) &&
3381 !IS_CTCE_WEOF( pDEVBLK->ctcexState ) )
3382 {
3383 strlcat( ctce_trace_xtra, "->CLR", sizeof( ctce_trace_xtra ) );
3384 }
3385
3386 // The source for reporting dependings on the Command X-fer
3387 // direction. The CTCE states are reported in lower case,
3388 // but a changed state is highlighted in upper case.
3389 if( eCTCE_Cmd_Xfr == CTCE_RCV )
3390 {
3391 ctce_Cmd = pDEVBLK->ctceyCmd;
3392 ctce_PktSeq = pSokBuf->PktSeq;
3393 ctce_state_r_xy[0] = 32 + *CTCE_StaStr[CTCE_STATE( pCTCE_Info->state_x_prev )];
3394 ctce_state_r_xy[1] = 32 + *CTCE_StaStr[CTCE_STATE( pCTCE_Info->state_y_prev )];
3395 if( ( pDEVBLK->ctcexState & 0x07 ) == ( pCTCE_Info->state_x_prev & 0x07 ) )
3396 {
3397 ctce_state_l_xy[0] = 32 + *CTCE_StaStr[CTCE_STATE( pDEVBLK->ctcexState )];
3398 }
3399 else
3400 {
3401 ctce_state_l_xy[0] = *CTCE_StaStr[CTCE_STATE( pDEVBLK->ctcexState )];
3402 }
3403 if( ( pDEVBLK->ctceyState & 0x07 ) == ( pCTCE_Info->state_y_prev & 0x07 ) )
3404 {
3405 ctce_state_l_xy[1] = 32 + *CTCE_StaStr[CTCE_STATE( pDEVBLK->ctceyState )];
3406 }
3407 else
3408 {
3409 ctce_state_l_xy[1] = *CTCE_StaStr[CTCE_STATE( pDEVBLK->ctceyState )];
3410 }
3411 ctce_state_verify = pDEVBLK->ctceyState & 0x07;
3412 }
3413 else
3414 {
3415 ctce_Cmd = pDEVBLK->ctcexCmd;
3416 ctce_PktSeq = pDEVBLK->ctcePktSeq;
3417 ctce_state_l_xy[0] = 32 + *CTCE_StaStr[CTCE_STATE( pCTCE_Info->state_x_prev )];
3418 ctce_state_l_xy[1] = 32 + *CTCE_StaStr[CTCE_STATE( pCTCE_Info->state_y_prev )];
3419 if( pDEVBLK->ctcexState == pCTCE_Info->state_x_prev )
3420 {
3421 ctce_state_r_xy[0] = 32 + *CTCE_StaStr[CTCE_STATE( pDEVBLK->ctcexState )];
3422 }
3423 else
3424 {
3425 ctce_state_r_xy[0] = *CTCE_StaStr[CTCE_STATE( pDEVBLK->ctcexState )];
3426 }
3427 if( pDEVBLK->ctceyState == pCTCE_Info->state_y_prev )
3428 {
3429 ctce_state_r_xy[1] = 32 + *CTCE_StaStr[CTCE_STATE( pDEVBLK->ctceyState )];
3430 }
3431 else
3432 {
3433 ctce_state_r_xy[1] = *CTCE_StaStr[CTCE_STATE( pDEVBLK->ctceyState )];
3434 }
3435 ctce_state_verify = pDEVBLK->ctcexState & 0x07;
3436
3437 // Report on the SCB returned if applicable.
3438 if( IS_CTCE_CCW_SCB( ctce_Cmd ) )
3439 {
3440 snprintf( ctce_trace_xtra_temp, sizeof( ctce_trace_xtra_temp ),
3441 " SCB=%02X=%s", pCTCE_Info->scb, CTCE_CmdStr[CTCE_CMD( pCTCE_Info->scb )] );
3442 strlcat( ctce_trace_xtra, ctce_trace_xtra_temp, sizeof( ctce_trace_xtra ) );
3443 }
3444 }
3445
3446 // Report on the device status.
3447 if( pCTCE_Info->busy_waits != 0 )
3448 {
3449 snprintf( ctce_trace_xtra_temp, sizeof( ctce_trace_xtra_temp ),
3450 " Busy_Waits=%d", pCTCE_Info->busy_waits );
3451 strlcat( ctce_trace_xtra, ctce_trace_xtra_temp, sizeof( ctce_trace_xtra ) );
3452 }
3453
3454 // Report on the WAIT RC if needed.
3455 if( ( eCTCE_Cmd_Xfr == CTCE_SND ) && ( pCTCE_Info->wait_rc != 0 ) )
3456 {
3457 snprintf( ctce_trace_xtra_temp, sizeof( ctce_trace_xtra_temp ),
3458 " WAIT->RC=%d", pCTCE_Info->wait_rc );
3459 strlcat( ctce_trace_xtra, ctce_trace_xtra_temp, sizeof( ctce_trace_xtra ) );
3460 }
3461
3462 // The "state mismatch" was used for debugging purposes
3463 // which would show logic errors.
3464 if( ( pCTCE_Info->state_new != ctce_state_verify )
3465 && !( ( !pCTCE_Info->sent ) && ( IS_CTCE_SEND( pCTCE_Info->actions ) ) ) )
3466 {
3467 snprintf( ctce_trace_xtra_temp, sizeof( ctce_trace_xtra_temp ),
3468 " CTCE_STATE MISMATCH %s!=%s(:FSM) !",
3469 CTCE_StaStr[ctce_state_verify],
3470 CTCE_StaStr[pCTCE_Info->state_new] );
3471 strlcat( ctce_trace_xtra, ctce_trace_xtra_temp, sizeof( ctce_trace_xtra ) );
3472 }
3473
3474 // The unit "Stat mismatch" was used for debugging purposes
3475 // which would show logic errors.
3476 if( ( *pUnitStat !=
3477 ( ( ( eCTCE_Cmd_Xfr == CTCE_RCV ) && ( IS_CTCE_MATCH( pCTCE_Info->actions ) ) )
3478 ? ( CSW_CE | CSW_DE ) : ( pCTCE_Info->x_unit_stat ) ) )
3479 && !( *pUnitStat & ( CSW_UC | CSW_UX | CSW_SM ) )
3480 && !( ( eCTCE_Cmd_Xfr == CTCE_RCV ) && ( IS_CTCE_WAIT( pCTCE_Info->actions ) ) )
3481 && ( ( eCTCE_Cmd_Xfr != CTCE_RCV ) || ( *pUnitStat != 0 ) )
3482 && !( pCTCE_Info->de_ready ) )
3483 {
3484 snprintf( ctce_trace_xtra_temp, sizeof( ctce_trace_xtra_temp ),
3485 " Stat MISMATCH %02X!=%02X(:FSM) !",
3486 *pUnitStat, pCTCE_Info->x_unit_stat );
3487 strlcat( ctce_trace_xtra, ctce_trace_xtra_temp, sizeof( ctce_trace_xtra ) );
3488 }
3489
3490 // Report a contention loser situation.
3491 if( pCTCE_Info->con_lost )
3492 {
3493 strlcat( ctce_trace_xtra, " CON_LOSER", sizeof( ctce_trace_xtra ) );
3494 }
3495
3496 // Report a contention winner situation.
3497 if( pCTCE_Info->con_won )
3498 {
3499 strlcat( ctce_trace_xtra, " CON_WINNER", sizeof( ctce_trace_xtra ) );
3500 }
3501
3502 /*
3503
3504 HHCCT079I <src_dev> CTCE: <direction> <dst_dev> <seq#> cmd=<cmd>=<cmd_hex>
3505 xy=<x_src><y_src><direction><x_dst><y_dst> l=<length> k=<chksum>
3506 Stat=<stat> <extra_msgs>
3507
3508 Explanation
3509 The CTCE device <local_dev> processes a <cmd> (hex value <cmd_hex>).
3510 The <direction> shows whether it originates locally (the x-side),
3511 and if it needs to be send (->) to the remote <remote_dev> device
3512 (the y-side), or if the command was received (<-) from the y-side.
3513 The command causes a state transition shown in <x_local><y_local>
3514 <direction> <x_remote><y_remote>, using single-letter presentations
3515 for these (p, c, r, w, a, n); the change is highlighted in uppercase.
3516 (p=Prepare, c=Control, r=Read, w=Write, a=Available, n=Not-Ready).
3517 The resulting unit device status is shown in hex <stat>. Extra
3518 action indications are given in <extra_msgs>, .e.g. WAIT for a
3519 matching command from the other y-side, raise ATTN at the other
3520 side which results in ATTN->RC=rc or is canceled ATTN->NONE,
3521 DE_READY->RC=rc showing DE singalling READY from the other side,
3522 and End-of-File being set (WEOF->SET) or cleared (WEOF->CLR) or
3523 just found to be set (WEOF). WEOF->UX shows when it generates a
3524 device Unit Exception. Other <extra_msgs> may appear.
3525
3526 Action
3527 None.
3528
3529 */
3530
3531 logmsg( _("HHCCT079I %04X CTCE: %s %.4s #%04X cmd=%s=%02X xy=%.2s%s%.2s l=%04X k=%08X %s%s%s%s%s%s\n"),
3532 CTCX_DEVNUM( pDEVBLK ), CTCE_XfrStr[eCTCE_Cmd_Xfr],
3533 CTCE_FILENAME, ctce_PktSeq,
3534 CTCE_CmdStr[CTCE_CMD( ctce_Cmd )], ctce_Cmd,
3535 ctce_state_l_xy, CTCE_XfrStr[eCTCE_Cmd_Xfr],
3536 ctce_state_r_xy,
3537 sCount, IS_CTCE_CCW_WRT( ctce_Cmd )
3538 ? CTCE_ChkSum( pCTCE_Buf + sizeof(CTCE_SOKPFX), sCount )
3539 : CTCE_ChkSum( pCTCE_Buf, pCTCE_Info->sok_buf_len ),
3540 ctce_trace_stat,
3541 CTCE_ACTIONS_PRT( pCTCE_Info->actions ),
3542 ctce_trace_xtra );
3543 if( pDEVBLK->ccwstep )
3544 packet_trace( (BYTE*)pCTCE_Buf, pCTCE_Info->sok_buf_len );
3545 return;
3546 }
3547
3548 // ---------------------------------------------------------------------
3549 // CTCE_connect_timeout
3550 // ---------------------------------------------------------------------
3551 //
3552 // connect but with a timeout parameter.
3553 //
3554
CTCE_Connect_Timeout(int sockfd,const struct sockaddr * saptr,const socklen_t salen,const int usec)3555 int CTCE_Connect_Timeout(int sockfd,
3556 const struct sockaddr* saptr,
3557 const socklen_t salen,
3558 const int usec)
3559 {
3560 int rc; // connect return code
3561 fd_set read_set, write_set; // socket sets for select
3562 static struct timeval connect_timeout; // max connect wait time
3563
3564 // Switch to non-blocking mode during the next connect.
3565 socket_set_blocking_mode( sockfd, 0 ) ;
3566 rc = connect( sockfd, saptr, salen );
3567
3568 // In case connect() did not complete immediately then we prepare
3569 // the select() to wait for the specified amount of time.
3570 if( rc < 0 )
3571 {
3572 FD_ZERO ( &read_set );
3573 FD_SET( sockfd, &read_set );
3574 write_set = read_set ;
3575 connect_timeout.tv_sec = 0;
3576 connect_timeout.tv_usec = usec;
3577
3578 // Then we issue select() until it returns a real error.
3579 // A zero return code means the select() timed out,
3580 // a positive one signifies the connect() took place.
3581 do
3582 {
3583 rc = select( sockfd + 1, &read_set, &write_set, NULL,
3584 usec ? &connect_timeout : NULL );
3585 } while( (rc < 0) && ( HSO_errno == HSO_EINTR ) );
3586
3587 if( rc == 0 )
3588 {
3589 close_socket( sockfd ) ;
3590 rc = -1;
3591 }
3592 }
3593
3594 // Switch back to original non-blocking mode and return
3595 socket_set_blocking_mode( sockfd, 1 ) ;
3596 return rc;
3597 }
3598