Rev 21 | Details | Compare with Previous | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line | 
|---|---|---|---|
| 21 | f9daq | 1 | /* | 
        
| 2 |    cc32lib_NT.c -- a simple access library for the PCICC32 PCI to CAMAC Interface | 
        ||
| 3 |                    from ARW Elektronik - the WINNT parts | 
        ||
| 4 | |||
| 5 |    (c) 2000 ARW Elektronik | 
        ||
| 6 | |||
| 7 |    this source code is published under GPL (Open Source). You can use, redistrubute and | 
        ||
| 8 |    modify it unless this header   is not modified or deleted. No warranty is given that | 
        ||
| 9 |    this software will work like expected. | 
        ||
| 10 |    This product is not authorized for use as critical component in life support systems | 
        ||
| 11 |    wihout the express written approval of ARW Elektronik Germany. | 
        ||
| 12 | |||
| 13 |    Please announce changes and hints to ARW Elektronik | 
        ||
| 14 | |||
| 15 |    derived from the previous WIN95 library                              AR   30.07.2000 | 
        ||
| 16 |    added buffer, UNTIL_NOT_Q and AUTOREAD functionality                 AR   17.03.2001 | 
        ||
| 17 | */ | 
        ||
| 18 | |||
| 19 | /*--- INCLUDES -----------------------------------------------------------------------------------*/ | 
        ||
| 20 | #include <windows.h> | 
        ||
| 21 | #include <stdio.h> | 
        ||
| 22 | #include <stdlib.h> | 
        ||
| 23 | #include <string.h> | 
        ||
| 24 | #include <errno.h> | 
        ||
| 25 | #include <winioctl.h> | 
        ||
| 26 | |||
| 27 | #include "pcicc32.h"  /* PCI common ioctl commands and structures between driver and library  */ | 
        ||
| 28 | #include "libcc32_NT.h"          /* shared header bewteen applictaion and library                        */ | 
        ||
| 29 | |||
| 30 | /*--- DEFINES ------------------------------------------------------------------------------------*/ | 
        ||
| 31 | #define DEFDEVICENAME "\\\\.\\PCICC32:\\CC32_xx" | 
        ||
| 32 | |||
| 33 | /*--- EXTERNALS ----------------------------------------------------------------------------------*/ | 
        ||
| 34 | |||
| 35 | /*--- TYPEDEFS -----------------------------------------------------------------------------------*/ | 
        ||
| 36 | typedef struct  | 
        ||
| 37 | { | 
        ||
| 38 | HANDLE nHandle; /* the handle of this device */  | 
        ||
| 39 | int nModuleNumber; /* the number of the module */  | 
        ||
| 40 | unsigned short wLastAccessWidth; /* the last parametrized data access width */  | 
        ||
| 41 | unsigned short wLastAttributes; /* the last Attributes to this channel */  | 
        ||
| 42 | unsigned long dwLastAccessAddress; /* the last access address to speed up */  | 
        ||
| 43 | } CC32_DEVICE_NT;  | 
        ||
| 44 | |||
| 45 | /*--- FUNCTIONS -----------------------------------------------------------------------*/ | 
        ||
| 46 | |||
| 47 | //-------------------------------------------------------------------------------------- | 
        ||
| 48 | // get the PCIADA status from the PCI side of the interface | 
        ||
| 49 | // | 
        ||
| 50 | static int getStatus(HANDLE nHandle, DWORD dwInterface, char *nTimeout, char *nLAM)  | 
        ||
| 51 | { | 
        ||
| 52 |         PCICC32_STATUS status; | 
        ||
| 53 | DWORD DIOC_count; // count of returned bytes of DeviceIoControl  | 
        ||
| 54 |         DWORD result; | 
        ||
| 55 | |||
| 56 | if (nHandle == (HANDLE)-1) return -1;  | 
        ||
| 57 | |||
| 58 | *nTimeout = *nLAM = 0;  | 
        ||
| 59 | |||
| 60 |         // attach a window into the CC32 space ---------------- | 
        ||
| 61 | result = DeviceIoControl(nHandle, PCICC32_GET_STATUS,  | 
        ||
| 62 | &dwInterface, sizeof(dwInterface),  | 
        ||
| 63 | &status, sizeof(status), &DIOC_count, NULL);  | 
        ||
| 64 | |||
| 65 | if (!result)  | 
        ||
| 66 | return GetLastError();  | 
        ||
| 67 |         else | 
        ||
| 68 |         { | 
        ||
| 69 | *nTimeout = (char)status.bTimeout;  | 
        ||
| 70 | *nLAM = (char)status.bInterrupt;  | 
        ||
| 71 | |||
| 72 | return 0;  | 
        ||
| 73 |         } | 
        ||
| 74 | } | 
        ||
| 75 | |||
| 76 | //-------------------------------------------------------------------------------------- | 
        ||
| 77 | // clear the PCIADA status | 
        ||
| 78 | // | 
        ||
| 79 | static int clearStatus(HANDLE nHandle, DWORD dwInterface)  | 
        ||
| 80 | { | 
        ||
| 81 | DWORD DIOC_count; // count of returned bytes of DeviceIoControl  | 
        ||
| 82 |         DWORD result; | 
        ||
| 83 | |||
| 84 | if (nHandle == (HANDLE)-1) return -1;  | 
        ||
| 85 | |||
| 86 |         // attach a window into the CC32 space ---------------- | 
        ||
| 87 | result = DeviceIoControl(nHandle, PCICC32_CLEAR_STATUS,  | 
        ||
| 88 | &dwInterface, sizeof(dwInterface),  | 
        ||
| 89 | NULL, 0, &DIOC_count, NULL);  | 
        ||
| 90 | |||
| 91 | if (!result)  | 
        ||
| 92 | return GetLastError();  | 
        ||
| 93 |         else | 
        ||
| 94 | return 0;  | 
        ||
| 95 | } | 
        ||
| 96 | |||
| 97 | //------------------------------------------------------------------------- | 
        ||
| 98 | // set the future access parameters - override the current | 
        ||
| 99 | // | 
        ||
| 100 | static int setAccessParameter(HANDLE hHandle, USHORT wAccessType, USHORT wBlockTransfer)  | 
        ||
| 101 | { | 
        ||
| 102 |         DWORD result; | 
        ||
| 103 | DWORD DIOC_count; // count of returned bytes of DeviceIoControl  | 
        ||
| 104 |     PCICC32_ACCESS_COMMAND access_parameter; | 
        ||
| 105 | |||
| 106 | access_parameter.wAccessType = wAccessType;  | 
        ||
| 107 | access_parameter.wBlockTransfer = wBlockTransfer;  | 
        ||
| 108 | |||
| 109 | result = DeviceIoControl(hHandle, PCICC32_SET_ACCESS_PARA,  | 
        ||
| 110 | &access_parameter, (DWORD)sizeof(access_parameter), NULL,  | 
        ||
| 111 | 0, &DIOC_count, NULL);  | 
        ||
| 112 | if (!result)  | 
        ||
| 113 | return GetLastError();  | 
        ||
| 114 |         else | 
        ||
| 115 | return 0;  | 
        ||
| 116 | } | 
        ||
| 117 | |||
| 118 | //------------------------------------------------------------------------- | 
        ||
| 119 | // create a DeviceName out of cszDeviceName and nIfcNum | 
        ||
| 120 | // | 
        ||
| 121 | static char *DeviceName(int nIfcNum)  | 
        ||
| 122 | { | 
        ||
| 123 | static char buffer[255];  | 
        ||
| 124 | char *ptr = buffer;  | 
        ||
| 125 | |||
| 126 | strncpy(buffer, DEFDEVICENAME, strlen(DEFDEVICENAME));  | 
        ||
| 127 | |||
| 128 | while (*ptr) ptr++;  | 
        ||
| 129 | |||
| 130 |         do | 
        ||
| 131 |         { | 
        ||
| 132 |                 ptr--; | 
        ||
| 133 | } while (*ptr != '_'); // step back until '-'  | 
        ||
| 134 | |||
| 135 |         ptr++; | 
        ||
| 136 | |||
| 137 | if (nIfcNum >= 10) // add the interface number  | 
        ||
| 138 |         { | 
        ||
| 139 | *ptr++ = '1';  | 
        ||
| 140 | nIfcNum -= 10;  | 
        ||
| 141 |         } | 
        ||
| 142 | |||
| 143 | *ptr++ = '0' + nIfcNum;  | 
        ||
| 144 | *ptr = 0;  | 
        ||
| 145 | |||
| 146 |         // a little help for the users | 
        ||
| 147 | return buffer;  | 
        ||
| 148 | } | 
        ||
| 149 | |||
| 150 | //------------------------------------------------------------------------- | 
        ||
| 151 | // open my path to the interface | 
        ||
| 152 | // | 
        ||
| 153 | static HANDLE openPath(char *name)  | 
        ||
| 154 | { | 
        ||
| 155 | return (HANDLE)CreateFile(  | 
        ||
| 156 |                      name, | 
        ||
| 157 | GENERIC_READ | GENERIC_WRITE,  | 
        ||
| 158 | 0,  | 
        ||
| 159 |                      NULL, | 
        ||
| 160 |                      OPEN_EXISTING, | 
        ||
| 161 |                      FILE_ATTRIBUTE_NORMAL, | 
        ||
| 162 | NULL  | 
        ||
| 163 | );  | 
        ||
| 164 | } | 
        ||
| 165 | |||
| 166 | //-------------------------------------------------------------------------------------- | 
        ||
| 167 | // open the device | 
        ||
| 168 | // | 
        ||
| 169 | int cc32_open_NT(char *cszPath, int nModuleNumber, void **handle)  | 
        ||
| 170 | { | 
        ||
| 171 | CC32_DEVICE_NT *dev;  | 
        ||
| 172 | int error = 0;  | 
        ||
| 173 | |||
| 174 | *handle = (void *)0;  | 
        ||
| 175 | |||
| 176 | dev = (CC32_DEVICE_NT *)malloc(sizeof(CC32_DEVICE_NT));  | 
        ||
| 177 | if (!dev) return errno;  | 
        ||
| 178 | |||
| 179 | dev->nModuleNumber = nModuleNumber;  | 
        ||
| 180 | dev->nHandle = INVALID_HANDLE_VALUE;  | 
        ||
| 181 | dev->wLastAccessWidth = 0xffff; /* invalidate for future use */  | 
        ||
| 182 | |||
| 183 |         // start the driver ------------------ | 
        ||
| 184 | dev->nHandle = openPath(DeviceName(nModuleNumber));  | 
        ||
| 185 | |||
| 186 | if (dev->nHandle == INVALID_HANDLE_VALUE)  | 
        ||
| 187 | error = GetLastError();  | 
        ||
| 188 |         else | 
        ||
| 189 |         { | 
        ||
| 190 | SetFilePointer(dev->nHandle, 0, NULL, FILE_BEGIN);  | 
        ||
| 191 | dev->dwLastAccessAddress = 0;  | 
        ||
| 192 | dev->wLastAttributes = 0;  | 
        ||
| 193 | dev->wLastAccessWidth = 0;  | 
        ||
| 194 |         } | 
        ||
| 195 | |||
| 196 | if (error)  | 
        ||
| 197 |         { | 
        ||
| 198 | free(dev);  | 
        ||
| 199 | return error;  | 
        ||
| 200 |         } | 
        ||
| 201 | |||
| 202 | *handle = (void *)dev;  | 
        ||
| 203 | |||
| 204 | return NO_ERROR;  | 
        ||
| 205 | } | 
        ||
| 206 | |||
| 207 | //-------------------------------------------------------------------------------------- | 
        ||
| 208 | // close the device | 
        ||
| 209 | // | 
        ||
| 210 | int cc32_close_NT(void *handle)  | 
        ||
| 211 | { | 
        ||
| 212 | CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;  | 
        ||
| 213 | int error = NO_ERROR;  | 
        ||
| 214 | |||
| 215 | if (dev)  | 
        ||
| 216 |         { | 
        ||
| 217 | if (dev->nHandle != INVALID_HANDLE_VALUE)  | 
        ||
| 218 | CloseHandle(dev->nHandle);  | 
        ||
| 219 | |||
| 220 | free(dev);  | 
        ||
| 221 |         } | 
        ||
| 222 |         else | 
        ||
| 223 | error = ERROR_INVALID_FUNCTION;  | 
        ||
| 224 | |||
| 225 | return error;  | 
        ||
| 226 | } | 
        ||
| 227 | |||
| 228 | //-------------------------------------------------------------------------------------- | 
        ||
| 229 | // read a word | 
        ||
| 230 | // | 
        ||
| 231 | unsigned short cc32_read_word_NT(void *handle, unsigned int N, unsigned int A, unsigned int F)  | 
        ||
| 232 | { | 
        ||
| 233 | register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;  | 
        ||
| 234 | unsigned long adr = NAF(N,A,F);  | 
        ||
| 235 | unsigned short buffer;  | 
        ||
| 236 | unsigned long bytesRead;  | 
        ||
| 237 | |||
| 238 |         // cache the data access width | 
        ||
| 239 | if (dev->wLastAccessWidth != WORD_ACCESS)  | 
        ||
| 240 |         { | 
        ||
| 241 | dev->wLastAccessWidth = WORD_ACCESS;  | 
        ||
| 242 | setAccessParameter(dev->nHandle, dev->wLastAccessWidth, dev->wLastAttributes);  | 
        ||
| 243 |         } | 
        ||
| 244 | |||
| 245 |         // cache the address | 
        ||
| 246 | if (dev->dwLastAccessAddress != adr)  | 
        ||
| 247 |         { | 
        ||
| 248 | SetFilePointer(dev->nHandle, adr, NULL, FILE_BEGIN);  | 
        ||
| 249 | dev->dwLastAccessAddress = adr;  | 
        ||
| 250 |         } | 
        ||
| 251 | |||
| 252 | ReadFile(dev->nHandle, &buffer, WORD_ACCESS, &bytesRead, NULL);  | 
        ||
| 253 | |||
| 254 | return buffer;  | 
        ||
| 255 | } | 
        ||
| 256 | |||
| 257 | //-------------------------------------------------------------------------------------- | 
        ||
| 258 | // read a long | 
        ||
| 259 | // | 
        ||
| 260 | unsigned long cc32_read_long_all_NT(void *handle, unsigned int N, unsigned int A, unsigned int F)  | 
        ||
| 261 | { | 
        ||
| 262 | register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;  | 
        ||
| 263 | unsigned long adr = NAF(N,A,F);  | 
        ||
| 264 | unsigned long buffer;  | 
        ||
| 265 | unsigned long bytesRead;  | 
        ||
| 266 | |||
| 267 |         // cache the data access width | 
        ||
| 268 | if (dev->wLastAccessWidth != LONG_ACCESS)  | 
        ||
| 269 |         { | 
        ||
| 270 | dev->wLastAccessWidth = LONG_ACCESS;  | 
        ||
| 271 | setAccessParameter(dev->nHandle, dev->wLastAccessWidth, dev->wLastAttributes);  | 
        ||
| 272 |         } | 
        ||
| 273 | |||
| 274 |         // cache the address | 
        ||
| 275 | if (dev->dwLastAccessAddress != adr)  | 
        ||
| 276 |         { | 
        ||
| 277 | SetFilePointer(dev->nHandle, adr, NULL, FILE_BEGIN);  | 
        ||
| 278 | dev->dwLastAccessAddress = adr;  | 
        ||
| 279 |         } | 
        ||
| 280 | |||
| 281 | ReadFile(dev->nHandle, &buffer, LONG_ACCESS, &bytesRead, NULL);  | 
        ||
| 282 | |||
| 283 | return buffer;  | 
        ||
| 284 | } | 
        ||
| 285 | |||
| 286 | //-------------------------------------------------------------------------------------- | 
        ||
| 287 | // read a long and get Q and X | 
        ||
| 288 | // | 
        ||
| 289 | unsigned long cc32_read_long_NT(void *handle, unsigned int N, unsigned int A, unsigned int F, char *Q, char *X)  | 
        ||
| 290 | { | 
        ||
| 291 | unsigned long erg = cc32_read_long_all_NT(handle, N, A, F);  | 
        ||
| 292 | |||
| 293 | *Q = (erg & 0x80000000) ? 1 : 0;  | 
        ||
| 294 | *X = (erg & 0x40000000) ? 1 : 0;  | 
        ||
| 295 | |||
| 296 | return erg & 0x00FFFFFF;  | 
        ||
| 297 | } | 
        ||
| 298 | |||
| 299 | //-------------------------------------------------------------------------------------- | 
        ||
| 300 | // write a word | 
        ||
| 301 | // | 
        ||
| 302 | void cc32_write_word_NT(void *handle, unsigned int N, unsigned int A, unsigned int F, unsigned short uwData)  | 
        ||
| 303 | { | 
        ||
| 304 | register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;  | 
        ||
| 305 | unsigned long adr = NAF(N,A,F);  | 
        ||
| 306 |         DWORD bytesWritten; | 
        ||
| 307 | |||
| 308 |         // cache the data access width | 
        ||
| 309 | if (dev->wLastAccessWidth != WORD_ACCESS)  | 
        ||
| 310 |         { | 
        ||
| 311 | dev->wLastAccessWidth = WORD_ACCESS;  | 
        ||
| 312 | setAccessParameter(dev->nHandle, dev->wLastAccessWidth, dev->wLastAttributes);  | 
        ||
| 313 |         } | 
        ||
| 314 | |||
| 315 |         // cache the address | 
        ||
| 316 | if (dev->dwLastAccessAddress != adr)  | 
        ||
| 317 |         { | 
        ||
| 318 | SetFilePointer(dev->nHandle, adr, NULL, FILE_BEGIN);  | 
        ||
| 319 | dev->dwLastAccessAddress = adr;  | 
        ||
| 320 |         } | 
        ||
| 321 | |||
| 322 | WriteFile(dev->nHandle, &uwData, WORD_ACCESS, &bytesWritten, NULL);  | 
        ||
| 323 | } | 
        ||
| 324 | |||
| 325 | //-------------------------------------------------------------------------------------- | 
        ||
| 326 | // write a long | 
        ||
| 327 | // | 
        ||
| 328 | void cc32_write_long_NT(void *handle, unsigned int N, unsigned int A, unsigned int F, unsigned long ulData)  | 
        ||
| 329 | { | 
        ||
| 330 | register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;  | 
        ||
| 331 | unsigned long adr = NAF(N,A,F);  | 
        ||
| 332 |         DWORD bytesWritten; | 
        ||
| 333 | |||
| 334 |         // cache the data access width | 
        ||
| 335 | if (dev->wLastAccessWidth != LONG_ACCESS)  | 
        ||
| 336 |         { | 
        ||
| 337 | dev->wLastAccessWidth = LONG_ACCESS;  | 
        ||
| 338 | setAccessParameter(dev->nHandle, dev->wLastAccessWidth, dev->wLastAttributes);  | 
        ||
| 339 |         } | 
        ||
| 340 | |||
| 341 |         // cache the address | 
        ||
| 342 | if (dev->dwLastAccessAddress != adr)  | 
        ||
| 343 |         { | 
        ||
| 344 | SetFilePointer(dev->nHandle, adr, NULL, FILE_BEGIN);  | 
        ||
| 345 | dev->dwLastAccessAddress = adr;  | 
        ||
| 346 |         } | 
        ||
| 347 | |||
| 348 | WriteFile(dev->nHandle, &ulData, LONG_ACCESS, &bytesWritten, NULL);  | 
        ||
| 349 | } | 
        ||
| 350 | |||
| 351 | //-------------------------------------------------------------------------------------- | 
        ||
| 352 | // clear the PCIADA status | 
        ||
| 353 | // | 
        ||
| 354 | int cc32_poll_error_NT(void *handle, char *nTimeout, char *nLam)  | 
        ||
| 355 | { | 
        ||
| 356 | CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;  | 
        ||
| 357 | int error;  | 
        ||
| 358 | |||
| 359 | if ((error = getStatus(dev->nHandle, dev->nModuleNumber, nTimeout, nLam)))  | 
        ||
| 360 | return error;  | 
        ||
| 361 | |||
| 362 | if (*nTimeout) /* clear error */  | 
        ||
| 363 |         { | 
        ||
| 364 | if ((error = clearStatus(dev->nHandle, dev->nModuleNumber)))  | 
        ||
| 365 | return error;  | 
        ||
| 366 |         } | 
        ||
| 367 | |||
| 368 | return NO_ERROR;  | 
        ||
| 369 | } | 
        ||
| 370 | |||
| 371 | //-------------------------------------------------------------------------------------- | 
        ||
| 372 | // read 'len' words or 'UNTIL_NOT_Q' from a address made out of N,A,F  | 
        ||
| 373 | // | 
        ||
| 374 | int cc32_read_word_buffer_NT(void * handle, unsigned int N, unsigned int A, unsigned int F,  | 
        ||
| 375 | unsigned short *pwBuffer, unsigned long *pdwLen)  | 
        ||
| 376 | { | 
        ||
| 377 | register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;  | 
        ||
| 378 | unsigned long adr = NAF(N,A,F);  | 
        ||
| 379 | unsigned long dwLen;  | 
        ||
| 380 | |||
| 381 |         // cache the data access width | 
        ||
| 382 | if (dev->wLastAccessWidth != WORD_ACCESS)  | 
        ||
| 383 |         { | 
        ||
| 384 | dev->wLastAccessWidth = WORD_ACCESS;  | 
        ||
| 385 | setAccessParameter(dev->nHandle, dev->wLastAccessWidth, dev->wLastAttributes);  | 
        ||
| 386 |         } | 
        ||
| 387 | |||
| 388 |         // cache the address | 
        ||
| 389 | if (dev->dwLastAccessAddress != adr)  | 
        ||
| 390 |         { | 
        ||
| 391 | SetFilePointer(dev->nHandle, adr, NULL, FILE_BEGIN);  | 
        ||
| 392 | dev->dwLastAccessAddress = adr;  | 
        ||
| 393 |         } | 
        ||
| 394 | |||
| 395 | *pdwLen <<= 1; // make bytes  | 
        ||
| 396 | dwLen = *pdwLen;  | 
        ||
| 397 | if (!ReadFile(dev->nHandle, pwBuffer, dwLen, pdwLen, NULL))  | 
        ||
| 398 | return GetLastError();  | 
        ||
| 399 | |||
| 400 | *pdwLen >>= 1; // make words  | 
        ||
| 401 | return 0;  | 
        ||
| 402 | } | 
        ||
| 403 | |||
| 404 | //-------------------------------------------------------------------------------------- | 
        ||
| 405 | // read 'len' longs or 'UNTIL_NOT_Q' from a address made out of N,A,F, mask 24 bits out | 
        ||
| 406 | // | 
        ||
| 407 | int cc32_read_long_buffer_NT(void * handle, unsigned int N, unsigned int A, unsigned int F,  | 
        ||
| 408 | unsigned long *pdwBuffer, unsigned long *pdwLen)  | 
        ||
| 409 | { | 
        ||
| 410 | register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;  | 
        ||
| 411 | unsigned long adr = NAF(N,A,F);  | 
        ||
| 412 | unsigned long *pdwPtr = pdwBuffer;  | 
        ||
| 413 | unsigned long *pdwEnd = pdwBuffer;  | 
        ||
| 414 | unsigned long dwLen;  | 
        ||
| 415 | |||
| 416 |         // cache the data access width | 
        ||
| 417 | if (dev->wLastAccessWidth != LONG_ACCESS)  | 
        ||
| 418 |         { | 
        ||
| 419 | dev->wLastAccessWidth = LONG_ACCESS;  | 
        ||
| 420 | setAccessParameter(dev->nHandle, dev->wLastAccessWidth, dev->wLastAttributes);  | 
        ||
| 421 |         } | 
        ||
| 422 | |||
| 423 |         // cache the address | 
        ||
| 424 | if (dev->dwLastAccessAddress != adr)  | 
        ||
| 425 |         { | 
        ||
| 426 | SetFilePointer(dev->nHandle, adr, NULL, FILE_BEGIN);  | 
        ||
| 427 | dev->dwLastAccessAddress = adr;  | 
        ||
| 428 |         } | 
        ||
| 429 | |||
| 430 | *pdwLen <<= 2; // make bytes  | 
        ||
| 431 | dwLen = *pdwLen;  | 
        ||
| 432 | if (!ReadFile(dev->nHandle, pdwBuffer, dwLen, pdwLen, NULL))  | 
        ||
| 433 | return GetLastError();  | 
        ||
| 434 | |||
| 435 | pdwEnd += *pdwLen;  | 
        ||
| 436 | while (pdwEnd < pdwPtr)  | 
        ||
| 437 | *pdwPtr++ &= 0x00FFFFFF; // mask Q and X bits  | 
        ||
| 438 | |||
| 439 | *pdwLen >>= 2; // make longs  | 
        ||
| 440 | return 0;  | 
        ||
| 441 | } | 
        ||
| 442 | |||
| 443 | //-------------------------------------------------------------------------------------- | 
        ||
| 444 | // read 'len' longs or 'UNTIL_NOT_Q' from a address made out of N,A,F, without interpretation  | 
        ||
| 445 | // | 
        ||
| 446 | int cc32_read_long_all_buffer_NT(void * handle, unsigned int N, unsigned int A, unsigned int F,  | 
        ||
| 447 | unsigned long *pdwBuffer, unsigned long *pdwLen)  | 
        ||
| 448 | { | 
        ||
| 449 | register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;  | 
        ||
| 450 | unsigned long adr = NAF(N,A,F);  | 
        ||
| 451 | unsigned long dwLen;  | 
        ||
| 452 | |||
| 453 |         // cache the data access width | 
        ||
| 454 | if (dev->wLastAccessWidth != LONG_ACCESS)  | 
        ||
| 455 |         { | 
        ||
| 456 | dev->wLastAccessWidth = LONG_ACCESS;  | 
        ||
| 457 | setAccessParameter(dev->nHandle, dev->wLastAccessWidth, dev->wLastAttributes);  | 
        ||
| 458 |         } | 
        ||
| 459 | |||
| 460 |         // cache the address | 
        ||
| 461 | if (dev->dwLastAccessAddress != adr)  | 
        ||
| 462 |         { | 
        ||
| 463 | SetFilePointer(dev->nHandle, adr, NULL, FILE_BEGIN);  | 
        ||
| 464 | dev->dwLastAccessAddress = adr;  | 
        ||
| 465 |         } | 
        ||
| 466 | |||
| 467 | *pdwLen <<= 2; // make bytes  | 
        ||
| 468 | dwLen = *pdwLen;  | 
        ||
| 469 | if (!ReadFile(dev->nHandle, pdwBuffer, dwLen, pdwLen, NULL))  | 
        ||
| 470 | return GetLastError();  | 
        ||
| 471 | |||
| 472 | *pdwLen >>= 2; // make longs  | 
        ||
| 473 | return 0;  | 
        ||
| 474 | } | 
        ||
| 475 | |||
| 476 | //-------------------------------------------------------------------------------------- | 
        ||
| 477 | // switch UNTIL_NOT_Q or AUTOREAD on or off  | 
        ||
| 478 | // | 
        ||
| 479 | int cc32_access_switch_NT(void *handle, unsigned short uwSwitch)  | 
        ||
| 480 | { | 
        ||
| 481 | register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;  | 
        ||
| 482 | |||
| 483 | dev->wLastAttributes = uwSwitch;  | 
        ||
| 484 | return setAccessParameter(dev->nHandle, dev->wLastAccessWidth, dev->wLastAttributes);  | 
        ||
| 485 | } | 
        ||
| 486 | |||
| 487 | //-------------------------------------------------------------------------------------- | 
        ||
| 488 | // switch interrupts on | 
        ||
| 489 | // | 
        ||
| 490 | int cc32_enable_interrupt_NT(void *handle)  | 
        ||
| 491 | { | 
        ||
| 492 | register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;  | 
        ||
| 493 |         DWORD result; | 
        ||
| 494 | DWORD DIOC_count; // count of returned bytes of DeviceIoControl  | 
        ||
| 495 |         PCICC32_IRQ_CONTROL irqCntrl; | 
        ||
| 496 | |||
| 497 | irqCntrl.dwInterface = 0; // don't bother at WINNT  | 
        ||
| 498 | irqCntrl.wEnable = 1; // enable it  | 
        ||
| 499 | |||
| 500 | result = DeviceIoControl(dev->nHandle, PCICC32_CONTROL_INTERRUPTS,  | 
        ||
| 501 | &irqCntrl, sizeof(irqCntrl), NULL, 0, &DIOC_count, NULL);  | 
        ||
| 502 | |||
| 503 | if (!result)  | 
        ||
| 504 | return GetLastError();  | 
        ||
| 505 |         else | 
        ||
| 506 | return NO_ERROR;  | 
        ||
| 507 | } | 
        ||
| 508 | |||
| 509 | //-------------------------------------------------------------------------------------- | 
        ||
| 510 | // switch interrupts off | 
        ||
| 511 | // | 
        ||
| 512 | int cc32_disable_interrupt_NT(void *handle)  | 
        ||
| 513 | { | 
        ||
| 514 | register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;  | 
        ||
| 515 |         DWORD result; | 
        ||
| 516 | DWORD DIOC_count; // count of returned bytes of DeviceIoControl  | 
        ||
| 517 |         PCICC32_IRQ_CONTROL irqCntrl; | 
        ||
| 518 | |||
| 519 | irqCntrl.dwInterface = 0; // don't bother at WINNT  | 
        ||
| 520 | irqCntrl.wEnable = 0; // disable it  | 
        ||
| 521 | |||
| 522 | result = DeviceIoControl(dev->nHandle, PCICC32_CONTROL_INTERRUPTS,  | 
        ||
| 523 | &irqCntrl, sizeof(irqCntrl), NULL, 0, &DIOC_count, NULL);  | 
        ||
| 524 | |||
| 525 | if (!result)  | 
        ||
| 526 | return GetLastError();  | 
        ||
| 527 |         else | 
        ||
| 528 | return NO_ERROR;  | 
        ||
| 529 | } | 
        ||
| 530 | |||
| 531 | //-------------------------------------------------------------------------------------- | 
        ||
| 532 | // wait blocking for the next interrupt | 
        ||
| 533 | // | 
        ||
| 534 | int cc32_get_interrupt_NT(void *handle, unsigned long *dwStatus)  | 
        ||
| 535 | { | 
        ||
| 536 | register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;  | 
        ||
| 537 |         DWORD result; | 
        ||
| 538 | DWORD DIOC_count; // count of returned bytes of DeviceIoControl  | 
        ||
| 539 |         PCICC32_IRQ_RESPONSE response; | 
        ||
| 540 | int nError;  | 
        ||
| 541 |         OVERLAPPED sOverlapped; | 
        ||
| 542 | |||
| 543 | sOverlapped.hEvent = NULL;  | 
        ||
| 544 | result = DeviceIoControl(dev->nHandle, PCICC32_INSTALL_IRQ_BLOCK,  | 
        ||
| 545 | NULL, 0, &response, sizeof(response), &DIOC_count, NULL);  | 
        ||
| 546 | |||
| 547 | *dwStatus = response.dwInterruptFlags;  | 
        ||
| 548 | |||
| 549 | if (!result)  | 
        ||
| 550 |         { | 
        ||
| 551 | nError = GetLastError();  | 
        ||
| 552 | |||
| 553 |                 // a real error  | 
        ||
| 554 | if ((nError != ERROR_IO_PENDING) && (nError != ERROR_SUCCESS))  | 
        ||
| 555 | return nError;  | 
        ||
| 556 | |||
| 557 |                 // my IO is pending - wait for it | 
        ||
| 558 | if (nError == ERROR_IO_PENDING)  | 
        ||
| 559 |                 { | 
        ||
| 560 | result = GetOverlappedResult(dev->nHandle, &sOverlapped, &DIOC_count, TRUE);  | 
        ||
| 561 | |||
| 562 | *dwStatus = response.dwInterruptFlags;  | 
        ||
| 563 | |||
| 564 | if (!result)  | 
        ||
| 565 |                         { | 
        ||
| 566 | nError = GetLastError(); // if it was cancelled  | 
        ||
| 567 | if (nError == ERROR_OPERATION_ABORTED)  | 
        ||
| 568 | return NO_ERROR; // accept it as 'normal'  | 
        ||
| 569 |                                 else | 
        ||
| 570 | return nError;  | 
        ||
| 571 |                         } | 
        ||
| 572 |                 } | 
        ||
| 573 |         } | 
        ||
| 574 | |||
| 575 | return NO_ERROR;  | 
        ||
| 576 | } | 
        ||
| 577 | |||
| 578 |