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