OpenCBM
PortAccess.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version
5  * 2 of the License, or (at your option) any later version.
6  *
7  * Copyright 2004-2006 Spiro Trikaliotis
8  *
9  */
10 
19 #include <initguid.h>
20 #include <wdm.h>
21 #include "cbm_driver.h"
22 
52 static NTSTATUS
53 ParPortIoctlInOut(IN PDEVICE_EXTENSION Pdx, IN ULONG Ioctl,
54  IN PVOID InBuffer, IN ULONG InBufferLength,
55  OUT PVOID OutBuffer, IN ULONG OutBufferLength)
56 {
57  IO_STATUS_BLOCK ioStatusBlock;
58  NTSTATUS ntStatus;
59  KEVENT event; // event to be signalled when the IOCTL has finished
60  PIRP irp;
61 
62  FUNC_ENTER();
63 
64  // Initialize the event which we will use to be notified
65  // when the IRP has finished
66 
67  DBG_IRQL( == PASSIVE_LEVEL);
68  KeInitializeEvent(&event, NotificationEvent, FALSE);
69 
70  ntStatus = STATUS_SUCCESS;
71 
72  // build an IRP for this IOCTL
73 
74  DBG_IRQL( == PASSIVE_LEVEL);
75  irp = IoBuildDeviceIoControlRequest(
76  Ioctl,
77  Pdx->ParallelPortFdo,
78  InBuffer,
79  InBufferLength,
80  OutBuffer,
81  OutBufferLength,
82  TRUE, // it's an internal device control
83  &event,
84  &ioStatusBlock
85  );
86 
87  if (irp)
88  {
89  PIO_STACK_LOCATION irpStack;
90 
91  // get the current IRP stack location
92 
93  DBG_IRQL( <= DISPATCH_LEVEL);
94  irpStack = IoGetNextIrpStackLocation(irp);
95 
96  // Reference the file object we are about to call.
97  // This ensures the driver is not removed while we call it,
98  // even if the underlying hardware is removed
99 
100  DBG_IRQL( <= DISPATCH_LEVEL);
101  ObReferenceObject(Pdx->ParallelPortFileObject);
102 
103  // tell the IRP stack location to which file object we are
104  // referring
105 
106  irpStack->FileObject = Pdx->ParallelPortFileObject;
107 
108  // Call the driver to perform the requested IOCTL
109 
110  DBG_IRQL( <= DISPATCH_LEVEL);
111  ntStatus = IoCallDriver(Pdx->ParallelPortFdo, irp);
112 
113  // We're done, we can dereference the file object again
114 
115  DBG_IRQL( <= DISPATCH_LEVEL);
116  ObDereferenceObject(Pdx->ParallelPortFileObject);
117 
118  if (!NT_SUCCESS(ntStatus))
119  {
120  DBG_WARN((DBG_PREFIX "IoCallDriver FAILED!"));
121  }
122  else
123  {
124  // wait for the IRP to be completed
125 
126  DBG_IRQL( <= DISPATCH_LEVEL /* = only if timeout of NULL */);
127  ntStatus = KeWaitForSingleObject(
128  &event,
129  Executive,
130  KernelMode,
131  FALSE, // we are not alertable
132  NULL);
133 
134  if (!NT_SUCCESS(ntStatus))
135  {
136  DBG_WARN((DBG_PREFIX "KeWaitForSingleObject FAILED!"));
137  }
138  }
139  }
140 
141  FUNC_LEAVE_NTSTATUS(ntStatus);
142 }
143 
156 NTSTATUS
157 ParPortAllocate(PDEVICE_EXTENSION Pdx)
158 {
159  NTSTATUS ntStatus;
160 
161  FUNC_ENTER();
162 
163  DBG_ASSERT(Pdx);
164  DBG_ASSERT(Pdx->ParallelPortAllocated == FALSE);
165 
166  // allocate the parallel port
167 
168  ntStatus = ParPortIoctlInOut(Pdx, IOCTL_INTERNAL_PARALLEL_PORT_ALLOCATE,
169  NULL, 0, NULL, 0);
170 
171  // if we were successfull, remember this in the pdx
172 
173  if (NT_SUCCESS(ntStatus))
174  {
175  Pdx->ParallelPortAllocated = TRUE;
176  }
177 
178  FUNC_LEAVE_NTSTATUS(ntStatus);
179 }
180 
194 NTSTATUS
195 ParPortFree(PDEVICE_EXTENSION Pdx)
196 {
197  NTSTATUS ntStatus = STATUS_SUCCESS;
198 
199  FUNC_ENTER();
200 
201  DBG_IRQL( == PASSIVE_LEVEL);
202 
203  DBG_ASSERT(Pdx != NULL);
204 
205  if (Pdx->ParallelPortAllocated == TRUE)
206  {
207  // Free the parallel port. An old implementation (v0.03) used
208  // IOCTL_INTERNAL_PARALLEL_PORT_FREE. But this is available only
209  // on WDM, that is, W2000, WXP, and above. In fact, MS specifically
210  // discourages using that IOCTL, and tells us to use FreePort()
211  // instead.
212  // Anyway, since I don't know what Microsoft will think in the future,
213  // I decided to keep the old implementation, too.
214 
215 #if 1
216  Pdx->PortInfo->FreePort(Pdx->PortInfo->Context);
217 #else
218  #error THIS IS ONLY AVAILABLE ON WDM! Thus, don't use it! (see comment above)
219  ntStatus = ParPortIoctlInOut(Pdx, IOCTL_INTERNAL_PARALLEL_PORT_FREE,
220  NULL, 0, NULL, 0);
221 #endif
222 
223  Pdx->ParallelPortAllocated = FALSE;
224  }
225 
226  FUNC_LEAVE_NTSTATUS(ntStatus);
227 
228 }
229 
252 NTSTATUS
253 ParPortInit(PUNICODE_STRING ParallelPortName, PDEVICE_EXTENSION Pdx)
254 {
255  NTSTATUS ntStatus;
256 
257  FUNC_ENTER();
258 
259  DBG_ASSERT(ParallelPortName);
260  DBG_ASSERT(Pdx);
261 
262  // First of all, get the PDEVICE_OBJECT of the parallel port driver
263 
264  DBG_IRQL( == PASSIVE_LEVEL);
265  ntStatus = IoGetDeviceObjectPointer(ParallelPortName,
266  FILE_READ_ATTRIBUTES,
267  &Pdx->ParallelPortFileObject,
268  &Pdx->ParallelPortFdo);
269 
270  if (!NT_SUCCESS(ntStatus))
271  {
272  DBG_WARN((DBG_PREFIX "IoGetDeviceObjectPointer() FAILED!"));
273  FUNC_LEAVE_NTSTATUS(ntStatus);
274  }
275 
276  // Allocate memory to hold to parallel port info
277 
278  DBG_IRQL( == PASSIVE_LEVEL);
279  Pdx->PortInfo = (PPARALLEL_PORT_INFORMATION) ExAllocatePoolWithTag(NonPagedPool,
280  sizeof(*Pdx->PortInfo), MTAG_PPINFO);
281 
282  // If we got memory, get the info out of the parallel port driver
283 
284  if (Pdx->PortInfo)
285  {
286  ntStatus = ParPortIoctlInOut(Pdx, IOCTL_INTERNAL_GET_PARALLEL_PORT_INFO,
287  NULL, 0,
288  Pdx->PortInfo, sizeof(*Pdx->PortInfo));
289  }
290  else
291  {
292  ntStatus = STATUS_INSUFFICIENT_RESOURCES;
293  }
294 
295  if (NT_SUCCESS(ntStatus))
296  {
297  Pdx->ParPortPortAddress = Pdx->PortInfo->Controller;
298  DBG_PPORT((DBG_PREFIX "Got parallel port information:"));
299  DBG_PPORT((DBG_PREFIX "- OriginalController = 0x%p", Pdx->PortInfo->OriginalController));
300  DBG_PPORT((DBG_PREFIX "- Controller = 0x%p", Pdx->PortInfo->Controller));
301  DBG_PPORT((DBG_PREFIX "- Span of controller = 0x%08x", Pdx->PortInfo->SpanOfController));
302  DBG_PPORT((DBG_PREFIX "- TryAllocatePort = 0x%p", Pdx->PortInfo->TryAllocatePort));
303  DBG_PPORT((DBG_PREFIX "- FreePort = 0x%p", Pdx->PortInfo->FreePort));
304  DBG_PPORT((DBG_PREFIX "- QueryNumWaiters = 0x%p", Pdx->PortInfo->QueryNumWaiters));
305  DBG_PPORT((DBG_PREFIX "- Context = 0x%p", Pdx->PortInfo->Context));
306  }
307 
308  // if we failed getting the parallel port info, but there was memory
309  // allocated, free the memory.
310 
311  if (!NT_SUCCESS(ntStatus) && Pdx->PortInfo)
312  {
313  DBG_IRQL( < DISPATCH_LEVEL);
314  ExFreePool(Pdx->PortInfo);
315  Pdx->PortInfo = NULL;
316  }
317 
318  FUNC_LEAVE_NTSTATUS(ntStatus);
319 }
320 
338 NTSTATUS
339 ParPortDeinit(PDEVICE_EXTENSION Pdx)
340 {
341  FUNC_ENTER();
342 
343  DBG_IRQL( <= DISPATCH_LEVEL);
344 
345  // If the file object was previously referenced
346  // (to make sure the parallel port driver is not
347  // removed while we access it), dereference it now.
348 
349  if (Pdx->ParallelPortFileObject)
350  {
351  DBG_IRQL( <= DISPATCH_LEVEL);
352  ObDereferenceObject(Pdx->ParallelPortFileObject);
353  Pdx->ParallelPortFileObject = NULL;
354  }
355 
356  // If we allocated memory for the parallel port info,
357  // free that now.
358  if (Pdx->PortInfo)
359  {
360  DBG_IRQL( < DISPATCH_LEVEL);
361  ExFreePool(Pdx->PortInfo);
362  Pdx->PortInfo = NULL;
363  }
364 
365  FUNC_LEAVE_NTSTATUS_CONST(STATUS_SUCCESS);
366 }
367 
369 #define DBG_PPORT_VERBOSE( _yy, _xxx, _type) \
370  DBG_PPORT((DBG_PREFIX " --- " #_xxx " = " _type, PnpInfo->_xxx))
371 
388 static BOOLEAN
389 ParPortGetPnpInformation(PDEVICE_EXTENSION Pdx, PPARALLEL_PNP_INFORMATION PnpInfo)
390 {
391  NTSTATUS ntStatus;
392  BOOLEAN success;
393 
394  FUNC_ENTER();
395 
396  // get the PNP, ECP and EPP info out of the parallel port
397 
398  ntStatus = ParPortIoctlInOut(Pdx, IOCTL_INTERNAL_GET_PARALLEL_PNP_INFO,
399  NULL, 0, PnpInfo, sizeof(*PnpInfo));
400 
401  if (!NT_SUCCESS(ntStatus))
402  {
403  // It is no problem if this fails. It only means we do not have to worry
404  // about ECP and EPP modes
405 
406  DBG_WARN((DBG_PREFIX "IOCTL_INTERNAL_GET_PARALLEL_PNP_INFO FAILED with %s", DebugNtStatus(ntStatus)));
407 
408  success = FALSE;
409  }
410  else
411  {
412  success = TRUE;
413 
414  //
415  // remember the ECP port address
416  //
417 
418  Pdx->ParPortEcpPortAddress = PnpInfo->EcpController;
419 
420  // Output some diagnostics for debugging purposes:
421 
422  DBG_PPORT((DBG_PREFIX "IOCTL_INTERNAL_GET_PARALLEL_PNP_INFO:"));
423  DBG_PPORT((DBG_PREFIX "EcpController = 0x%p", PnpInfo->EcpController));
424 
425  DBG_PPORT_VERBOSE(PHYSICAL_ADDRESS, OriginalEcpController, "0x%p");
426  DBG_PPORT_VERBOSE(PUCHAR, EcpController, "0x%p");
427  DBG_PPORT_VERBOSE(ULONG, SpanOfEcpController, "%u");
428  DBG_PPORT_VERBOSE(ULONG, PortNumber, "%u (deprecated, do not use!)");
429  DBG_PPORT_VERBOSE(ULONG, HardwareCapabilities, "%u");
430  DBG_PPORT_VERBOSE(PPARALLEL_SET_CHIP_MODE, TrySetChipMode, "0x%p");
431  DBG_PPORT_VERBOSE(PPARALLEL_CLEAR_CHIP_MODE, ClearChipMode, "0x%p");
432  DBG_PPORT_VERBOSE(ULONG, FifoDepth, "%u");
433  DBG_PPORT_VERBOSE(ULONG, FifoWidth, "%u");
434  DBG_PPORT_VERBOSE(PHYSICAL_ADDRESS, EppControllerPhysicalAddress, "0x%p");
435  DBG_PPORT_VERBOSE(ULONG, SpanOfEppController, "%u");
436  DBG_PPORT_VERBOSE(ULONG, Ieee1284_3DeviceCount, "%u");
437  DBG_PPORT_VERBOSE(PPARALLEL_TRY_SELECT_ROUTINE, TrySelectDevice, "0x%p");
438  DBG_PPORT_VERBOSE(PPARALLEL_DESELECT_ROUTINE, DeselectDevice, "0x%p");
439  DBG_PPORT_VERBOSE(PVOID, Context, "0x%p");
440  DBG_PPORT_VERBOSE(ULONG, CurrentMode, "0x%04x");
441  DBG_PPORT_VERBOSE(PWSTR, PortName, "%ws")
442  }
443 
444  FUNC_LEAVE_BOOLEAN(success);
445 }
446 #undef DBG_PPORT_VERBOSE
447 
460 NTSTATUS
461 ParPortSetModeWdm(PDEVICE_EXTENSION Pdx)
462 {
463  PARALLEL_PNP_INFORMATION pnpInformation;
464  NTSTATUS ntStatus;
465 
466  FUNC_ENTER();
467 
468  // do not assume success for the following
469 
470  ntStatus = STATUS_INVALID_PARAMETER;
471 
472  if (ParPortGetPnpInformation(Pdx, &pnpInformation))
473  {
474 #if DBG
475  PUCHAR ecr;
476 
477  if (pnpInformation.EcpController != 0)
478  {
479  ecr = pnpInformation.EcpController + ECR_OFFSET;
480 
481  DBG_PPORT((DBG_PREFIX "We're having an ECP controller: ECR = %08x", ecr));
482  DBG_PPORT((DBG_PREFIX " --- ECR = %02x", READ_PORT_UCHAR(ecr)));
483  }
484 #endif
485 
486  // now, we want to set the parallel port mode. This does only
487  // make sense if we have functions for setting and clearing the
488  // chip mode
489 
490  if (pnpInformation.TrySetChipMode && pnpInformation.ClearChipMode)
491  {
492  // Does our parallel port have the capability to be set into
493  // byte mode? If not, it does not make sense to change the mode
494 
495  if (pnpInformation.HardwareCapabilities & PPT_BYTE_PRESENT)
496  {
497  DBG_PPORT((DBG_PREFIX "Trying to set Chip mode to BYTE MODE..."));
498 
499  // try to set the chip mode to byte mode
500 
501  DBG_IRQL( <= DISPATCH_LEVEL);
502  ntStatus = pnpInformation.TrySetChipMode(pnpInformation.Context, ECR_BYTE_MODE);
503 
504  DBG_PPORT((DBG_PREFIX " --- TrySetChipMode returned with %s", DebugNtStatus(ntStatus)));
505  }
506  else
507  {
508  // no byte mode available. Thus, we want to make sure we have at
509  // least SPP byte.
510 
511  DBG_PPORT((DBG_PREFIX "****************************** NO BYTE MODE PRESENT, making sure to have SPP mode!!!"));
512  ParPortUnsetMode(Pdx);
513 
514  // Anyway, we don't want to fail this call just because the user
515  // does not have an EPP or ECP port:
516 
517  ntStatus = STATUS_SUCCESS;
518  }
519 #if DBG
520  if (pnpInformation.EcpController != 0)
521  {
522  DBG_PPORT((DBG_PREFIX " --- ECR = %02x", READ_PORT_UCHAR(ecr)));
523  }
524 #endif
525  }
526  else
527  {
528  DBG_PPORT((DBG_PREFIX " --- TrySetChipMode or ClearChipmode not available!"));
529  }
530  }
531 
532  FUNC_LEAVE_NTSTATUS(ntStatus);
533 }
534 
548 NTSTATUS
549 ParPortUnsetModeWdm(PDEVICE_EXTENSION Pdx)
550 {
551  PARALLEL_PNP_INFORMATION pnpInformation;
552  NTSTATUS ntStatus;
553 
554  FUNC_ENTER();
555 
556  // assume we have success in the following
557 
558  ntStatus = STATUS_SUCCESS;
559 
560  if (ParPortGetPnpInformation(Pdx, &pnpInformation))
561  {
562 #if DBG
563  PUCHAR ecr;
564 
565  if (pnpInformation.EcpController != 0)
566  {
567  ecr = pnpInformation.EcpController + ECR_OFFSET;
568 
569  DBG_PPORT((DBG_PREFIX "We're having an ECP controller: ECR = %08x", ecr));
570 
571  DBG_PPORT((DBG_PREFIX " --- ECR = %02x", READ_PORT_UCHAR(ecr)));
572  }
573 #endif
574 
575  // If we have the ClearChipMode function, try to unset the last set mode
576 
577  if (pnpInformation.ClearChipMode)
578  {
579  DBG_PPORT((DBG_PREFIX "Trying to unset Chip mode..."));
580 
581  DBG_IRQL( <= DISPATCH_LEVEL);
582  ntStatus = pnpInformation.ClearChipMode(
583  pnpInformation.Context,
584  (UCHAR) pnpInformation.CurrentMode);
585 
586  DBG_PPORT((DBG_PREFIX " --- ClearChipMode returned with %s", DebugNtStatus(ntStatus)));
587 
588  // If we did not have success, this is no problem.
589  // This means that we did not set the mode in the first place,
590  // thus, ignore that error.
591 
592  if (ntStatus == STATUS_UNSUCCESSFUL)
593  {
594  ntStatus = STATUS_SUCCESS;
595  }
596  }
597 
598 #if DBG
599  if (pnpInformation.EcpController != 0)
600  {
601  DBG_PPORT((DBG_PREFIX " --- ECR = %02x", READ_PORT_UCHAR(ecr)));
602  }
603 #endif
604  }
605 
606  FUNC_LEAVE_NTSTATUS(ntStatus);
607 }
608 
627 NTSTATUS
628 ParPortAllocInterrupt(PDEVICE_EXTENSION Pdx, PKSERVICE_ROUTINE Isr)
629 {
630  NTSTATUS ntStatus;
631 
632  FUNC_ENTER();
633 
634  DBG_IRQL( == PASSIVE_LEVEL);
635 
636  DBG_ASSERT(Pdx);
637  DBG_ASSERT(Isr);
638  DBG_ASSERT(Pdx->ParallelPortAllocatedInterrupt == FALSE);
639 
640  Pdx->Pisr.InterruptServiceRoutine = Isr;
641  Pdx->Pisr.InterruptServiceContext = Pdx;
642  Pdx->Pisr.DeferredPortCheckRoutine = NULL;
643  Pdx->Pisr.DeferredPortCheckContext = NULL;
644 
645  // try to allocate the interrupt via the IOCTL
646 
647  ntStatus = ParPortIoctlInOut(Pdx, IOCTL_INTERNAL_PARALLEL_CONNECT_INTERRUPT,
648  &Pdx->Pisr, sizeof(Pdx->Pisr),
649  &Pdx->Pii, sizeof(Pdx->Pii));
650 
651  // If we had success, remember this in the Pdx.
652 
653  if (NT_SUCCESS(ntStatus))
654  {
655  Pdx->ParallelPortAllocatedInterrupt = TRUE;
656  }
657  else
658  {
659  DBG_WARN((DBG_PREFIX "Allocation of Interrupt FAILED!"));
660  LogErrorOnly(Pdx->Fdo, CBM_NO_ISR);
661  }
662 
663  FUNC_LEAVE_NTSTATUS(ntStatus);
664 }
665 
679 NTSTATUS
680 ParPortFreeInterrupt(PDEVICE_EXTENSION Pdx)
681 {
682  NTSTATUS ntStatus;
683 
684  FUNC_ENTER();
685 
686  DBG_IRQL( == PASSIVE_LEVEL);
687 
688  DBG_ASSERT(Pdx);
689 
690  // If the interrupt was previously allocated, free that
691 
692  if (Pdx->ParallelPortAllocatedInterrupt == TRUE)
693  {
694  ntStatus = ParPortIoctlInOut(Pdx, IOCTL_INTERNAL_PARALLEL_DISCONNECT_INTERRUPT,
695  &Pdx->Pisr, sizeof(Pdx->Pisr),
696  NULL, 0);
697 
698  Pdx->ParallelPortAllocatedInterrupt = FALSE;
699  }
700  else
701  {
702  // If we did not have any interrupt, this function was successfull,
703  // thus, report this as return value.
704 
705  ntStatus = STATUS_SUCCESS;
706  }
707 
708  FUNC_LEAVE_NTSTATUS(ntStatus);
709 }
710 
728 NTSTATUS
729 ParPortAllowInterruptIoctl(PDEVICE_EXTENSION Pdx)
730 {
731  PDEVICE_OBJECT pdo;
732  NTSTATUS ntStatus;
733  HANDLE handleReg;
734  ULONG OldStateEnableConnectInterruptIoctl;
735  ULONG OldStateFilterResourceMethod;
736 
737  FUNC_ENTER();
738 
739  DBG_ASSERT(Pdx);
740 
741  // open the hardware key to the parallel port
742 
743  ntStatus = cbm_registry_open_hardwarekey(&handleReg, &pdo, Pdx);
744 
745  if (NT_SUCCESS(ntStatus))
746  {
747  // We could open the hardware key. Now, we get the old values,
748  // and set the values we need.
749 
750  // EnableConnectInterruptIoctl allows us to issue the
751  // IOCTL, or it blocks us. If this registry key is not set,
752  // the parport driver will not even consider to let us obtain
753  // the interrupt.
754  // The possible values are:
755  // - 0: The IOCTL is forbidden (default)
756  // - else: The IOCTL is allowed
757  // This value is tested with every call to the IOCTL
758 
759  ntStatus = cbm_registry_read_ulong(handleReg, L"EnableConnectInterruptIoctl",
760  &OldStateEnableConnectInterruptIoctl);
761 
762  // If the value was not there, remember it in the OldState var
763 
764  if (ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
765  {
766  OldStateEnableConnectInterruptIoctl = -1;
767  ntStatus = STATUS_SUCCESS;
768  }
769 
770  // FilterResourceMethod tells the parallel port if it should try
771  // to get the interrupt itself in the first place. If the parallel port
772  // does not have an interrupt, we cannot obtain it ourselves.
773  // The possible values are:
774  // - 0: Try to not obtain the interrupt, if such a hardware
775  // configuration exists
776  // - 1: Force not to use the interrupt (default)
777  // - 2: Always use the interrupt
778  // Unfortunately, this entry is only checked on device initialization.
779  // Because of this, the parport needs to be restarted for this change
780  // to take effect.
781 
782  ntStatus = cbm_registry_read_ulong(handleReg, L"FilterResourceMethod",
783  &OldStateFilterResourceMethod);
784 
785  // If the value was not there, remember it in the OldState var
786 
787  if (ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
788  {
789  OldStateFilterResourceMethod = -1;
790  ntStatus = STATUS_SUCCESS;
791  }
792 
793  // If the registry entries had the wrong values, set them to the ones
794  // we need here
795 
796  if (NT_SUCCESS(ntStatus) && OldStateEnableConnectInterruptIoctl != 1)
797  {
798  ntStatus = cbm_registry_write_ulong(handleReg, L"EnableConnectInterruptIoctl", 1);
799  }
800 
801  if (NT_SUCCESS(ntStatus) && OldStateFilterResourceMethod != 2)
802  {
803  ntStatus = cbm_registry_write_ulong(handleReg, L"FilterResourceMethod", 2);
804  }
805 
806  // we're done, we do not need the hardware key anymore
807 
808  cbm_registry_close_hardwarekey(handleReg, pdo);
809  }
810 
811  FUNC_LEAVE_NTSTATUS(ntStatus);
812 }
#define MTAG_PPINFO
Definition: memtags.h:32
#define DBG_WARN(_xxx)
Definition: debug.h:395
NTSTATUS ParPortUnsetModeWdm(PDEVICE_EXTENSION Pdx)
Unset the operational mode of the parallel port, WDM Version.
Definition: PortAccess.c:549
#define FUNC_LEAVE_BOOLEAN(_xxx)
Definition: debug.h:356
NTSTATUS ParPortAllocInterrupt(PDEVICE_EXTENSION Pdx, PKSERVICE_ROUTINE Isr)
Allocate an interrupt routine for a parallel port.
Definition: PortAccess.c:628
NTSTATUS cbm_registry_open_hardwarekey(OUT PHANDLE HandleKey, OUT PDEVICE_OBJECT *Pdo, IN PDEVICE_EXTENSION Pdx)
Open the hardware key for another driver.
Definition: util-reg.c:95
NTSTATUS ParPortFreeInterrupt(PDEVICE_EXTENSION Pdx)
Free an interrupt routine for a parallel port after using it.
Definition: PortAccess.c:680
NTSTATUS ParPortDeinit(PDEVICE_EXTENSION Pdx)
Undoes anything ParPortInit has done.
Definition: PortAccess.c:339
NTSTATUS cbm_registry_read_ulong(IN HANDLE HandleKey, IN PCWSTR KeyName, OUT PULONG Value)
Read a ULONG value out of a registry key.
Definition: util-reg.c:299
#define DBG_ASSERT(_xxx)
Definition: debug.h:401
NTSTATUS ParPortFree(PDEVICE_EXTENSION Pdx)
Free a parallel port after using it.
Definition: PortAccess.c:195
#define DBG_PPORT(_xxx)
Definition: debug.h:391
NTSTATUS ParPortAllowInterruptIoctl(PDEVICE_EXTENSION Pdx)
Set registry key such that we can get the interrupt of a parallel port.
Definition: PortAccess.c:729
NTSTATUS ParPortUnsetMode(PDEVICE_EXTENSION Pdx)
Unset the operational mode of the parallel port.
#define FUNC_ENTER()
Definition: debug.h:347
const UCHAR * DebugNtStatus(NTSTATUS Value)
Return the description of an NTSTATUS code.
Definitions for the opencbm driver.
#define DBG_PREFIX
Definition: debug.h:320
#define LogErrorOnly(_Fdo_, _UniqueErrorValue_)
Definition: util.h:35
NTSTATUS cbm_registry_close_hardwarekey(IN HANDLE HandleKey, IN PDEVICE_OBJECT Pdo)
Close a hardware registry key.
Definition: util-reg.c:260
NTSTATUS ParPortSetModeWdm(PDEVICE_EXTENSION Pdx)
Set the operational mode of the parallel port, WDM Version.
Definition: PortAccess.c:461
NTSTATUS ParPortAllocate(PDEVICE_EXTENSION Pdx)
Allocate a parallel port for using it.
Definition: PortAccess.c:157
#define DBG_PPORT_VERBOSE(_yy, _xxx, _type)
Definition: PortAccess.c:369
NTSTATUS ParPortInit(PUNICODE_STRING ParallelPortName, PDEVICE_EXTENSION Pdx)
Initialize the knowledge on a parallel port.
Definition: PortAccess.c:253
NTSTATUS cbm_registry_write_ulong(IN HANDLE HandleKey, IN PCWSTR KeyName, IN ULONG Value)
Write a ULONG value out of a registry key.
Definition: util-reg.c:356
#define READ_PORT_UCHAR(_x_)
READ_PORT_UCHAR replacement for debugging.
Definition: i_iec.h:211