1 /* QETH.C (c) Copyright Jan Jaeger, 2004-2009 */
2 /* OSA Express */
3
4 /* This module contains device handling functions for the */
5 /* OSA Express emulated card */
6
7 /* Device module hdtqeth.dll devtype QETH (config) */
8 /* hercules.cnf: */
9 /* 0A00-0A02 QETH <optional parameters> */
10
11 #include "hstdinc.h"
12 #include "hercules.h"
13 #include "devtype.h"
14
15
16 #if defined(WIN32) && defined(OPTION_DYNAMIC_LOAD) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_)
17 SYSBLK *psysblk;
18 #define sysblk (*psysblk)
19 #endif
20
21
22 static BYTE sense_id_bytes[] = { 0xff,
23 0x17, 0x31, 0x01, /* D/T */
24 0x17, 0x32, 0x01, /* CU/T */
25 0x00,
26 0x40, 0xfa, 0x01, 0x00, /* RCD CIW */
27 0x03, 0xfc, 0x01, 0x00, /*Ena Q CIW */
28 0x04, 0xfd, 0x01, 0x00 /* Act Q CIW */
29 };
30
31
32 /*-------------------------------------------------------------------*/
33 /* Initialize the device handler */
34 /*-------------------------------------------------------------------*/
qeth_init_handler(DEVBLK * dev,int argc,char * argv[])35 static int qeth_init_handler ( DEVBLK *dev, int argc, char *argv[] )
36 {
37 UNREFERENCED(argc);
38 UNREFERENCED(argv);
39
40 logmsg(D_("dev(%4.4x) experimental driver\n"),dev->devnum);
41
42 dev->numdevid = sizeof(sense_id_bytes);
43 logmsg(D_("senseidnum=%d\n"),dev->numdevid);
44 memcpy(dev->devid, sense_id_bytes, sizeof(sense_id_bytes));
45 dev->devtype = dev->devid[1] << 8 | dev->devid[2];
46
47 dev->pmcw.flag4 |= PMCW4_Q;
48
49 if(!group_device(dev,3))
50 {
51 logmsg(D_("group device(%4.4x) pending\n"),dev->devnum);
52 return 0;
53 }
54 else
55 {
56 int i;
57 logmsg(D_("group = ( "));
58 for(i = 0; i < dev->group->acount; i++)
59 logmsg("%4.4x ",dev->group->memdev[i]->devnum);
60 logmsg(") complete\n");
61 }
62
63 return 0;
64 } /* end function qeth_init_handler */
65
66
67 /*-------------------------------------------------------------------*/
68 /* Query the device definition */
69 /*-------------------------------------------------------------------*/
qeth_query_device(DEVBLK * dev,char ** class,int buflen,char * buffer)70 static void qeth_query_device (DEVBLK *dev, char **class,
71 int buflen, char *buffer)
72 {
73 BEGIN_DEVICE_CLASS_QUERY( "QETH", dev, class, buflen, buffer );
74
75 snprintf (buffer, buflen, "\n");
76
77 } /* end function qeth_query_device */
78
79
80 /*-------------------------------------------------------------------*/
81 /* Close the device */
82 /*-------------------------------------------------------------------*/
qeth_close_device(DEVBLK * dev)83 static int qeth_close_device ( DEVBLK *dev )
84 {
85 UNREFERENCED(dev);
86
87 /* Close the device file */
88
89 return 0;
90 } /* end function qeth_close_device */
91
92
93 /*-------------------------------------------------------------------*/
94 /* Execute a Channel Command Word */
95 /*-------------------------------------------------------------------*/
qeth_execute_ccw(DEVBLK * dev,BYTE code,BYTE flags,BYTE chained,U16 count,BYTE prevcode,int ccwseq,BYTE * iobuf,BYTE * more,BYTE * unitstat,U16 * residual)96 static void qeth_execute_ccw ( DEVBLK *dev, BYTE code, BYTE flags,
97 BYTE chained, U16 count, BYTE prevcode, int ccwseq,
98 BYTE *iobuf, BYTE *more, BYTE *unitstat, U16 *residual )
99 {
100 int rc = 0; /* Return code */
101 int num; /* Number of bytes to move */
102 int blocksize = 1024;
103 #define CONFIG_DATA_SIZE 1024
104
105 UNREFERENCED(flags);
106 UNREFERENCED(prevcode);
107 UNREFERENCED(ccwseq);
108 UNREFERENCED(chained);
109 UNREFERENCED(rc);
110 UNREFERENCED(blocksize);
111
112 /* Process depending on CCW opcode */
113 switch (code) {
114
115 case 0x01:
116 /*---------------------------------------------------------------*/
117 /* WRITE */
118 /*---------------------------------------------------------------*/
119 logmsg(D_("Write dev(%4.4x)\n"),dev->devnum);
120 #define WR_SIZE 0x22
121
122 /* Calculate number of bytes to read and set residual count */
123 num = (count < WR_SIZE) ? count : WR_SIZE;
124 *residual = count - num;
125 if (count < WR_SIZE) *more = 1;
126
127 /* Return normal status */
128 *unitstat = CSW_CE | CSW_DE;
129 break;
130
131 case 0x02:
132 /*---------------------------------------------------------------*/
133 /* READ */
134 /*---------------------------------------------------------------*/
135 logmsg(D_("Read dev(%4.4x)\n"),dev->devnum);
136
137 #define RD_SIZE 0x22
138 /* Calculate number of bytes to read and set residual count */
139 num = (count < RD_SIZE) ? count : RD_SIZE;
140 *residual = count - num;
141 if (count < RD_SIZE) *more = 1;
142
143 /* Return normal status */
144 *unitstat = CSW_CE | CSW_DE;
145 break;
146
147 case 0x03:
148 /*---------------------------------------------------------------*/
149 /* CONTROL NO-OPERATION */
150 /*---------------------------------------------------------------*/
151 logmsg(D_("NOP dev(%4.4x)\n"),dev->devnum);
152 *residual = 0;
153 *unitstat = CSW_CE | CSW_DE;
154 break;
155
156 case 0x04:
157 /*---------------------------------------------------------------*/
158 /* SENSE */
159 /*---------------------------------------------------------------*/
160 logmsg(D_("Sense dev(%4.4x)\n"),dev->devnum);
161 /* Calculate residual byte count */
162 num = (count < dev->numsense) ? count : dev->numsense;
163 *residual = count - num;
164 if (count < dev->numsense) *more = 1;
165
166 /* Copy device sense bytes to channel I/O buffer */
167 memcpy (iobuf, dev->sense, num);
168
169 /* Clear the device sense bytes */
170 memset (dev->sense, 0, sizeof(dev->sense));
171
172 /* Return unit status */
173 *unitstat = CSW_CE | CSW_DE;
174 break;
175
176 case 0xE4:
177 /*---------------------------------------------------------------*/
178 /* SENSE ID */
179 /*---------------------------------------------------------------*/
180 logmsg(D_("Sense ID dev(%4.4x)\n"),dev->devnum);
181 /* Calculate residual byte count */
182 num = (count < dev->numdevid) ? count : dev->numdevid;
183 *residual = count - num;
184 if (count < dev->numdevid) *more = 1;
185
186 /* Copy device identifier bytes to channel I/O buffer */
187 memcpy (iobuf, dev->devid, num);
188
189 /* Return unit status */
190 *unitstat = CSW_CE | CSW_DE;
191 break;
192
193 case 0xFA:
194 /*---------------------------------------------------------------*/
195 /* READ CONFIGURATION DATA */
196 /*---------------------------------------------------------------*/
197 logmsg(D_("Read Configuration Data dev(%4.4x)\n"),dev->devnum);
198 /* Calculate residual byte count */
199 num = (count < CONFIG_DATA_SIZE) ? count : CONFIG_DATA_SIZE;
200 *residual = count - num;
201 if (count < CONFIG_DATA_SIZE) *more = 1;
202
203 /* Clear the configuration data area */
204 memset (iobuf, 0x00, CONFIG_DATA_SIZE);
205
206 /* Return unit status */
207 *unitstat = CSW_CE | CSW_DE;
208 break;
209
210
211 case 0xFC:
212 /*---------------------------------------------------------------*/
213 /* ESTABLISH QUEUES */
214 /*---------------------------------------------------------------*/
215 logmsg(D_("Establish Queues dev(%4.4x)\n"),dev->devnum);
216 /* Calculate residual byte count */
217 num = (count < CONFIG_DATA_SIZE) ? count : CONFIG_DATA_SIZE;
218 *residual = count - num;
219 if (count < CONFIG_DATA_SIZE) *more = 1;
220
221 memset (iobuf, 0x00, CONFIG_DATA_SIZE);
222
223 /* INCOMPLETE ZZ
224 * QUEUES MUST BE SETUP HERE
225 */
226
227 /* Return unit status */
228 *unitstat = CSW_CE | CSW_DE;
229 break;
230
231 case 0xFD:
232 /*---------------------------------------------------------------*/
233 /* ACTIVATE QUEUES */
234 /*---------------------------------------------------------------*/
235 logmsg(D_("Activate Queues dev(%4.4x)\n"),dev->devnum);
236 /* Calculate residual byte count */
237 num = (count < CONFIG_DATA_SIZE) ? count : CONFIG_DATA_SIZE;
238 *residual = count - num;
239 if (count < CONFIG_DATA_SIZE) *more = 1;
240
241 memset (iobuf, 0x00, CONFIG_DATA_SIZE);
242
243 /* INCOMPLETE ZZ
244 * QUEUES MUST BE HANDLED HERE, THIS CCW WILL ONLY EXIT
245 * IN CASE OF AN ERROR OR A HALT, CLEAR OR CANCEL SIGNAL
246 */
247
248 /* Return unit status */
249 *unitstat = CSW_CE | CSW_DE;
250 break;
251
252 default:
253 /*---------------------------------------------------------------*/
254 /* INVALID OPERATION */
255 /*---------------------------------------------------------------*/
256 logmsg(D_("Unkown CCW dev(%4.4x) code(%2.2x)\n"),dev->devnum,code);
257 /* Set command reject sense byte, and unit check status */
258 dev->sense[0] = SENSE_CR;
259 *unitstat = CSW_CE | CSW_DE | CSW_UC;
260
261 } /* end switch(code) */
262
263 } /* end function qeth_execute_ccw */
264
265
266 /*-------------------------------------------------------------------*/
267 /* Signal Adapter Initiate Input */
268 /*-------------------------------------------------------------------*/
qeth_initiate_input(DEVBLK * dev,U32 qmask)269 static int qeth_initiate_input(DEVBLK *dev, U32 qmask)
270 {
271 UNREFERENCED(qmask);
272
273 logmsg(D_("SIGA-r dev(%4.4x) qmask(%8.8x)\n"),dev->devnum);
274 return 0;
275 }
276
277
278 /*-------------------------------------------------------------------*/
279 /* Signal Adapter Initiate Output */
280 /*-------------------------------------------------------------------*/
qeth_initiate_output(DEVBLK * dev,U32 qmask)281 static int qeth_initiate_output(DEVBLK *dev, U32 qmask)
282 {
283 UNREFERENCED(qmask);
284
285 logmsg(D_("SIGA-w dev(%4.4x) qmask(%8.8x)\n"),dev->devnum);
286 return 0;
287 }
288
289
290 #if defined(OPTION_DYNAMIC_LOAD)
291 static
292 #endif
293 DEVHND qeth_device_hndinfo =
294 {
295 &qeth_init_handler, /* Device Initialisation */
296 &qeth_execute_ccw, /* Device CCW execute */
297 &qeth_close_device, /* Device Close */
298 &qeth_query_device, /* Device Query */
299 NULL, /* Device Start channel pgm */
300 NULL, /* Device End channel pgm */
301 NULL, /* Device Resume channel pgm */
302 NULL, /* Device Suspend channel pgm */
303 NULL, /* Device Read */
304 NULL, /* Device Write */
305 NULL, /* Device Query used */
306 NULL, /* Device Reserve */
307 NULL, /* Device Release */
308 NULL, /* Device Attention */
309 NULL, /* Immediate CCW Codes */
310 &qeth_initiate_input, /* Signal Adapter Input */
311 &qeth_initiate_output, /* Signal Adapter Output */
312 NULL, /* Hercules suspend */
313 NULL /* Hercules resume */
314 };
315
316 /* Libtool static name colision resolution */
317 /* note : lt_dlopen will look for symbol & modulename_LTX_symbol */
318 #if !defined(HDL_BUILD_SHARED) && defined(HDL_USE_LIBTOOL)
319 #define hdl_ddev hdtqeth_LTX_hdl_ddev
320 #define hdl_depc hdtqeth_LTX_hdl_depc
321 #define hdl_reso hdtqeth_LTX_hdl_reso
322 #define hdl_init hdtqeth_LTX_hdl_init
323 #define hdl_fini hdtqeth_LTX_hdl_fini
324 #endif
325
326
327 #if defined(OPTION_DYNAMIC_LOAD)
328 HDL_DEPENDENCY_SECTION;
329 {
330 HDL_DEPENDENCY(HERCULES);
331 HDL_DEPENDENCY(DEVBLK);
332 HDL_DEPENDENCY(SYSBLK);
333 }
334 END_DEPENDENCY_SECTION
335
336
337 #if defined(WIN32) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_)
338 #undef sysblk
339 HDL_RESOLVER_SECTION;
340 {
341 HDL_RESOLVE_PTRVAR( psysblk, sysblk );
342 }
343 END_RESOLVER_SECTION
344 #endif
345
346
347 HDL_DEVICE_SECTION;
348 {
349 HDL_DEVICE(QETH, qeth_device_hndinfo );
350 }
351 END_DEVICE_SECTION
352 #endif
353