SDC C-Project CF Review 프로그램
LYW
2021-10-14 26e2541b87ca76e16cf69399eb9a3cce62d2e864
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
/*
 * mckernel.h
 *
 * 32-bit Motion Control Device Driver
 *
 * Definition of interface between hardware-specific portions of
 * kernel driver and the helper library mckernel.lib
 *
 * The hardware-specific portion of a motion control driver will
 * have an NT-specific DriverEntry function that will call Init()
 * to initialise the helper library after performing hardware detect and
 * initialise. All NT interaction will then be done by the library mckernel.lib
 * calling back to the hardware-specific code only through the dispatch
 * table below.
 *
 * All h/w specific functions are given a pointer to a PDEVICE_INFO structure
 * which they can pass to Inp(), Outp(). GetHWInfo() will return a
 * pointer to the hardware-specific data structure requested from Init().
 *
 */
 
#ifndef _MCKERNEL_
  #define _MCKERNEL_
 
/* include necessary headers so that hardware-specific callers do not
 * explicitly reference NT-specific headers.
 */
 
  #if defined(_NT)
    #include <ntddk.h>
  #else
typedef long NTSTATUS;
  #endif
 
  #include <windef.h>
  #include <mcstruct.h>
  #include <mioctl.h>
 
#ifdef _OLD_DLL
  #define PT_PMAC1  1
  #define PT_PMAC2  2
  #define PT_PMACUL 3
  #define PT_PMAC   4
  #define PT_PMAC1T 5
  #define PT_PMAC2T 6
  #define PT_PMACUT 7
  #define PT_UMAC   8
#endif
 
/*****************************************************************************
 * hardware-independent device-extension data structure - opaque to
 * h/w specific functions.
*****************************************************************************/
typedef struct _DEVICE_INFO DEVICE_INFO, *PDEVICE_INFO;
 
/*****************************************************************************
 Callbacks to h/w specific code
 
 These are the hardware-specific functions called from the dispatcher
*****************************************************************************/
typedef struct __CALLBACK
{
  // called on device open/close - optional routines
  BOOLEAN (*DeviceOpenFunc)(PDEVICE_INFO);
  BOOLEAN (*DeviceCloseFunc)(PDEVICE_INFO);
  BOOLEAN (*InterruptInitFunc)(PDEVICE_INFO pDevInfo, ULONG interruptMask);
  BOOLEAN (*InterruptTermFunc)(PDEVICE_INFO);
 
  // returns TRUE if Interrupt needs Service
  ULONG   (*InterruptAcknowledge)(PDEVICE_INFO);
 
  // called on driver-unload
  BOOLEAN (*CleanupFunc)(PDEVICE_INFO);
 
} _CALLBACK, * P_CALLBACK;
 
/*****************************************************************************
 
 Support functions for NT
*****************************************************************************/
  #if defined(_NT)
/*
 * PmacCreateDevice
 *
 * Create the device object, and any necessary related setup, and
 * allocate device extension data. The device extension data is
 * a DEVICE_INFO struct plus however much data the caller wants for
 * hardware-specific data.
 *
 * parameters:
 *  pDriverObject - pointer to driver object (arg to DriverEntry)
 *  RegistryPathName - entry for this driver in registry (arg to DriverEntry)
 *  HWInfoSize - amount of data to allocate at end of DeviceExtension
 *  DeviceNumber - the nth Pmac to create a device object for
 *
 * returns pointer to device extension data as DEVICE_INFO struct.
 */
PDEVICE_OBJECT
  PmacCreateDevice(
      PDRIVER_OBJECT  pDriverObject,
      PUNICODE_STRING RegistryPathName,
      ULONG           HWInfoSize,
    UCHAR           DeviceNumber);
 
PDEVICE_INFO PmacDeleteDevice(PDRIVER_OBJECT  pDriverObject,PDEVICE_INFO pDevInfo);
 
/*
 * GetResources
 *
 * map port and frame buffer into system address space or i/o space, and
 * report resource usage of the ports, interrupt and physical memory
 * address used.
 *
 * Note: We do not connect the interrupt: this is not done until
 * a subsequent call to ConnectInterrupt(). We do, however, report
 * usage of the interrupt.
 *
 * we return TRUE if success, or FALSE if we couldn't get the resources.
 */
BOOLEAN
  GetResources(
      PDEVICE_INFO pDevInfo,
      PDRIVER_OBJECT pDriverObject,
      DWORD  PortBase,
      ULONG   NrOfPorts,
      ULONG   Interrupt,
      BOOLEAN bLatched,
      DWORD   FrameBuffer);
 
// the dispatch routine to which all IRPs go
NTSTATUS Dispatch(
    IN PDEVICE_OBJECT pDeviceObject,
    IN PIRP pIrp
);
 
 
// cancel routine - set as cancel routine for pending irps (wait-error
// or add-buffer). Called to de-queue and complete them if cancelled.
VOID Cancel(
    IN PDEVICE_OBJECT pDeviceObject,
    IN PIRP pIrp
);
 
// call to unload or abort load of the driver
VOID Cleanup(PDRIVER_OBJECT pDriverObject);
 
/* interrupt service routine - returns TRUE if interrupt handled.
 * all interrupts come in here and are then dispatched to hw ack routine
 * the Context pointer is a pointer to DEVICE_INFO.
 */
BOOLEAN
  InterruptService(
      IN PKINTERRUPT pInterruptObject,
      IN PVOID Context
  );
 
/*
 * DPC routine scheduled in MC_InterruptService.
 */
VOID
  Deferred(
      PKDPC pDpc,
      PDEVICE_OBJECT pDeviceObject,
      PIRP pIrpNotUsed,
      PVOID Context
  );
 
/*
 * extract the next item from a cancellable queue of irps
 * if bCancelHeld is true, then we already hold the cancel spinlock so we
 * should not try to get it
 */
PIRP
  ExtractNextIrp(
      PLIST_ENTRY pQueueHead,
      BOOLEAN bCancelHeld
  );
 
/*
 * extract a specific IRP from the given queue, while possibly holding the
 * cancel spinlock already.
 */
PIRP
  ExtractThisIrp(
      PLIST_ENTRY pHead,
      PIRP pIrpToFind,
      BOOLEAN bCancelHeld
  );
 
/*
 * interlocked queue access functions
 */
/*
 * QueueRequest
 *
 * Add an irp to a cancellable queue.
 * Check the cancel flag and return FALSE if cancelled.
 * otherwise set the cancel routine and add to queue.
 *
 */
BOOLEAN
  QueueRequest(
      PIRP pIrp,
      PLIST_ENTRY pQueueHead,
      PDRIVER_CANCEL pCancelFunc
  );
 
/*
 * ReplaceRequest
 *
 * return a request to the head of a cancellable queue
 *
 */
BOOLEAN
  ReplaceRequest(
      PIRP pIrp,
      PLIST_ENTRY pQueueHead,
      PDRIVER_CANCEL pCancelFunc
  );
 
 
/*
 * increment the skipcount, and complete a wait-error irp if there
 * is one waiting.
 */
VOID
  ReportSkip(
      PDEVICE_INFO pDevInfo
  );
 
/*
 * queue a wait-error request to the queue of cancellable wait-error requests,
 * and return the irp's status (pending, cancelled, etc);
 *
 * When queuing, check the cancel flag and insert the correct cancel routine.
 *
 * If there is a skip-count to report, then:
 *   --- if there is another irp on the q already complete that and leave
 *       the current irp pending.
 *   -- otherwise return STATUS_SUCCESSFUL for this IRP, having written out
 *      the result data.
 *
 * Even if cancelled or complete, IoCompleteRequest will NOT have been called
 * for this request.
 */
NTSTATUS
QueueWaitError(
    PDEVICE_INFO pDevInfo,
    PIRP pIrp
);
 
/*****************************************************************************
 
*****************************************************************************/
  #endif // _NT
 
/*
 * ConnectInterrupt
 *
 * This assumes that GetResources() has already been called to report the
 * resource usage, and that the _CALLBACK table has been set up
 * to handle interrupts.
 *
 * returns TRUE if success.
 */
BOOLEAN ConnectInterrupt(
    PDEVICE_INFO pDevInfo,
    BOOLEAN bLatched);
 
 
 
// get the hardware specific portion of the device extension
PVOID GetHWInfo(PDEVICE_INFO);
 
// get card information stored for user retrieval
LONG  atol(PCHAR s,PCHAR *ep); // like strtol
int   GetRomDate(PDEVICE_INFO pDevInfo);
int   GetRomVersion(PDEVICE_INFO pDevInfo);
BOOL  GetLinkList(PDEVICE_INFO pDevInfo);
BOOL  GetLDSList(PDEVICE_INFO pDevInfo);
int   GetIVariableStr(PDEVICE_INFO pDevInfo,PCHAR str,UINT maxchar,UINT num);
int   GetPmacType(PDEVICE_INFO pDevInfo);
DWORD SetMaxMotors(PDEVICE_INFO pDevInfo);
LONG  GetIVariableLong(PDEVICE_INFO pDevInfo,ULONG num,LONG def);
BOOL  SetIVariableLong(PDEVICE_INFO pDevInfo,ULONG num,LONG val);
BOOL  GetScales(PDEVICE_INFO pDevInfo);
int   GetDPRAMAddress(PDEVICE_INFO pDevInfo,PDWORD adr);
BOOL  ConfigureDPRAM(PDEVICE_INFO pDevInfo);
int   SaveConfiguration(PDEVICE_INFO pDevInfo);
 
//============================================================================
// PORT Related macro,defines and functions
  #define PORT_STALL_USEC    5     // usec stall per retry period
 
// determine if PMAC card can be found on this port address
BOOL CardOnPort(PDEVICE_INFO pDevInfo);
 
//----------------------------------------------------------------------------------
//  Specialized flush, determines if PMAC is in the bus.
//  THEORY: If no card exists in bus at the specified i/o address then it
//      will appear that there is an infinite amount of characters of type
//      0xFF to be stripped.  This function is useful to initiate communication
//      on the bus since a deadlock situation may occur otherwise.
//----------------------------------------------------------------------------------
BOOL PmacPingAndClean(PDEVICE_INFO pDevInfo);
 
// output one byte from the port at bOffset offset from the port base address
VOID Outp(PDEVICE_INFO pDevInfo, BYTE bOffset, BYTE bData);
// input one byte from the port at bOffset offset from the port base address
BYTE Inp(PDEVICE_INFO pDevInfo, BYTE bOffset);
 
// flush bus port
void FlushPort(PDEVICE_INFO pDevInfo);
// write a character to PMAC bus port
int  WriteCharPort(PDEVICE_INFO pDevInfo, UCHAR outchar);
// write buffer to bus port
int  WriteLinePort(PDEVICE_INFO pDevInfo,PUCHAR str);
// see if port has a read ready
BOOL PortIsReadReady(PDEVICE_INFO pDevInfo);
// read bus port into buffer until eol with wait
int ReadLinePort(PDEVICE_INFO pDevInfo,PUCHAR str,UINT maxchar);
// send a command then read bus port into buffer until eot or err or timeout
int GetResponsePort(PDEVICE_INFO pDevInfo,PUCHAR s,UINT maxchar,
                        PUCHAR outstr);
// Get response to control characters
int GetControlResponse(PDEVICE_INFO pDevInfo ,CHAR inChar,
             PCHAR outStr,DWORD maxChars);
 
//============================================================================
// MEMORY Related macro,defines and functions
  #define MEM_STALL_USEC    5     // usec stall per retry period
 
/*
The macros below are based on this PMAC DPRAM ASCII structure
 
struct ascii {
  unsigned short  sendready:1;  // Y:$D18B output control word 0x62C
  unsigned short    pad:15;
  unsigned short  ctrlchar;     // X:$D18B control character
  char      outstr[MAXAOUT];    // $D18C - $D1B3 output string buffer
  unsigned short  instatus;     // Y:$D1B4 input control word 0x6D0
  unsigned short  charcount;    // X:$D1B4 input character count
  char      instr[MAXAIN];      // $D1B5 - $D1F4 input string buffer
};
*/
 
// Turbo ASCII memory port macros ---------------------------------------------
// Base = 0x0E9C
  #define SENDREADY_T     (READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0xE9C)) == 0)
  #define NOT_SENDREADY_T (READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0xE9C)) > 0)
  #define SET_SENDREADY_T (WRITE_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0xE9C),1))
  #define CTRL_CHAR_T     (PUCHAR)(pDevInfo->FrameBase + 0xE9E)
  #define READREADY_T     (READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0xF40)) > 0)
  #define NOT_READREADY_T (READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0xF40)) == 0)
  #define FLUSH_ACK_READY_T ((READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0xF40)) & 0x001F) == 0x0018)
  #define SET_READREADY_T (WRITE_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0xF40),0))
  #define ERROR_SET_T     ((READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0xF40)) & 0x8000) > 0)
  #define ERROR_T         (((READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0xF40))) &  0x0F) + \
                        (((READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0xF40))) >> 4) & 0x0F) * 10)
  #define NUM_CHARS_T     (READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0xF42)) - 1)
  #define MEM_ACK_T       ((READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0xF40)) & 0x000F) == 0x0006)
  #define MEM_CR_T        ((READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0xF40)) & 0x000F) == 0x000D)
  #define MEM_PMACREADY_T (READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0xF40)))
  #define MEM_USR_T       ((READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0xF40)) & 0x0300) != 0)
 
 
// Pmac1/2 ASCII memory port macros ---------------------------------------------
// Base = 0x062C
  #define SENDREADY     (READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0x62C)) == 0)
  #define NOT_SENDREADY (READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0x62C)) > 0)
  #define SET_SENDREADY (WRITE_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0x62C),1))
  #define CTRL_CHAR     (PUCHAR)(pDevInfo->FrameBase + 0x62E)
  #define READREADY     (READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0x6D0)) > 0)
  #define NOT_READREADY (READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0x6D0)) == 0)
  #define FLUSH_ACK_READY ((READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0x6D0)) & 0x001F) == 0x0018)
  #define SET_READREADY (WRITE_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0x6D0),0))
  #define ERROR_SET     ((READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0x6D0)) & 0x8000) > 0)
  #define ERROR2        (((READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0x6D0))) &  0x0F) + \
                        (((READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0x6D0))) >> 4) & 0x0F) * 10)
  #define NUM_CHARS     (READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0x6D2)) - 1)
  #define MEM_ACK       ((READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0x6D0)) & 0x000F) == 0x0006)
  #define MEM_CR        ((READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0x6D0)) & 0x000F) == 0x000D)
  #define MEM_PMACREADY (READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0x6D0)))
  #define MEM_USR       ((READ_REGISTER_USHORT((PUSHORT)(pDevInfo->FrameBase + 0x6D0)) & 0x0300) != 0)
 
// determine if PMAC card has DPRAM and can communicate through it
BOOL CardHasMem(PDEVICE_INFO pDevInfo);
// configure card memory address
void ConfigureMem(PDEVICE_INFO pDevInfo);
// Get a portion of DPRAM
UINT GetMem(PDEVICE_INFO pDevInfo,PBYTE pbData,WORD wDprOffset,WORD wLength);
// Set a portion of DPRAM
UINT SetMem(PDEVICE_INFO pDevInfo,PBYTE pbData,WORD wDprOffset,WORD wLength);
// Get a bit from DPRAM DWORD
UINT GetMemBit(PDEVICE_INFO pDevInfo,PMEM_BUFFER_BIT pMemBufferBits);
// Set a bit DPRAM DWORD
UINT SetMemBit(PDEVICE_INFO pDevInfo,PMEM_BUFFER_BIT pMemBufferBits);
// Get a bit range of DPRAM DWORD
UINT GetMemBits(PDEVICE_INFO pDevInfo,PMEM_BUFFER_BITS pMemBufferBits);
// Set a bit range of DPRAM DWORD
UINT SetMemBits(PDEVICE_INFO pDevInfo,PMEM_BUFFER_BITS pMemBufferBits);
// flush mem port
void FlushMem(PDEVICE_INFO pDevInfo);
// write a character to pmac dpram ascii port (ie. 'ch' + '\0')
UINT WriteCharMem(PDEVICE_INFO pDevInfo,UCHAR outchar);
// write a control character to pmac dpram ascii port
UINT WriteCtrlCharMem(PDEVICE_INFO pDevInfo,UCHAR outchar);
// write a character to frame ASCII buffer
UINT WriteLineMem(PDEVICE_INFO pDevInfo,PUCHAR str);
// see if dpram port has a read ready
BOOL MemIsReadReady(PDEVICE_INFO pDevInfo);
 
//----------------------------------------------------------------------------
// see what DPRAM is ready with, send,cmd,ack,err
//----------------------------------------------------------------------------
WORD  MemIsReadReadyEx(PDEVICE_INFO pDevInfo);
 
// read frame memory into buffer until eol with wait
int  ReadLineMem(PDEVICE_INFO pDevInfo,PUCHAR str);
//----------------------------------------------------------------------------------
// This function sends the requested control character between 1 - 26 to the
// PMAC. If the request is known not to return any characters it sets the EOT
// status bit then exits immediately to avoid any timeout.  If the request is known
// to return "1" line of data the function grabs the data then returns with EOT set.
// If the funtion returns "n" lines of data the function doesn't attempt to grab
// any data and doesn't set the EOT status so it is up to the caller to grab the data
//-----------------------------------------------------------------------------------
int GetControlResponseMem(PDEVICE_INFO pDevInfo ,CHAR inChar,PCHAR outStr,DWORD maxChars);
 
/*
 * i/o memory on adapter cards such as the frame buffer memory cannot
 * be accessed like ordinary memory on all processors (especially alpha).
 * You must read and write this memory using the following macros. These are
 * wrappers for the appropriate NT macros.
 */
 
// return one ULONG from the frame buffer at p
  #ifdef i386
 
    #define ReadIOMemoryULONG(p)     ( * (DWORD volatile *)p)
 
// return a word from the frame buffer at p
    #define ReadIOMemoryUSHORT(p)    ( * (USHORT volatile *)p)
 
// return a byte from the frame buffer at p
    #define ReadIOMemoryBYTE(p)      ( * (unsigned char volatile *) p)
 
  #else
 
    #define ReadIOMemoryULONG(p)     READ_REGISTER_ULONG((PUCHAR)p)
 
// return a word from the frame buffer at p
    #define ReadIOMemoryUSHORT(p)    READ_REGISTER_USHORT((PUCHAR)p)
 
// return a byte from the frame buffer at p
    #define ReadIOMemoryBYTE(p)      READ_REGISTER_UCHAR(p)
 
  #endif
 
// read a block of c bytes from the frame buffer at s to memory at d
  #define ReadIOMemoryUCHAR(d, s, c)   READ_REGISTER_BUFFER_UCHAR(s, d, c)
 
// write a byte b to the frame buffer at p
  #define WriteIOMemoryBYTE(p, b)  WRITE_REGISTER_UCHAR(p, b)
 
// write a word w to the frame buffer at p
  #define WriteIOMemoryUSHORT(p, w)    WRITE_REGISTER_USHORT((PUSHORT)p, w)
 
// write a ULONG l to the frame buffer at p
  #define WriteIOMemoryULONG(p, l)     WRITE_REGISTER_ULONG((PULONG)p, l)
 
// write a block of c bytes to the frame buffer d from memory at s
  #define WriteIOMemoryUCHAR(d, s, c)  WRITE_REGISTER_BUFFER_UCHAR(d, s, c)
 
 
P_CALLBACK GetCallbackTable(PDEVICE_INFO);
 
/* get a pointer to the frame buffer mapped into system memory */
PUCHAR GetFrameBuffer(PDEVICE_INFO);
 
 
/* this function is a wrapper for KeSynchronizeExecution (at least in the NT
 * version). It will call back the function specified with the context
 * argument specified, having first disabled the video interrupt in
 * a multi-processor safe way.
 */
typedef BOOLEAN (*PSYNC_ROUTINE)(PVOID);
BOOLEAN SynchronizeExecution(PDEVICE_INFO, PSYNC_ROUTINE, PVOID);
 
/*
 * This function can be used like SynchronizeExecution(), to sync
 * between the captureservice routine and the passive-level requests. This
 * will not necessarily disable interrupts. On win-16, this function may be
 * the same as SynchronizeExecution(). On NT, the CaptureService func
 * runs as a DPC, at a lower interrupt priority than the isr itself, and
 * so can be protected using this (spinlock-based) function without having
 * to disable all interrupts.
 */
BOOLEAN SynchronizeDPC(PDEVICE_INFO, PSYNC_ROUTINE, PVOID);
 
 
/*
 * AccessData() gives access to the data in kernel mode in a safe way.
 * It calls the given function with the address and size of the buffer
 * after any necessary mapping, and wrapped in exception handlers
 * as necessary.
 *
 * This function cannot be called from the InterruptAcknowledge or
 * ServiceCapture call back functions - it must be running in the
 * context of the calling thread (in kernel mode).
 */
typedef BOOLEAN (*PACCESS_ROUTINE)(PDEVICE_INFO, PUCHAR, ULONG, PVOID);
BOOLEAN AccessData(PDEVICE_INFO, PUCHAR, ULONG, PACCESS_ROUTINE, PVOID);
 
/* these functions allocate and free non-paged memory for use
 * in kernel mode, including at interrupt time.
 */
PVOID AllocMem(PDEVICE_INFO, ULONG);
VOID FreeMem(PDEVICE_INFO, PVOID, ULONG);
 
 
/*
 * delay for a number of milliseconds. This is accurate only to
 * +- 15msecs at best.
 */
VOID Delay(int nMillisecs);
 
/* block for given number of microseconds by polling. Not recommended
 * for more than 25 usecs.
 */
VOID Stall(int nMicrosecs);
 
#endif // _MCKERNEL_