00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00020 #include <initguid.h>
00021 #include <wdm.h>
00022 #include "cbm_driver.h"
00023
00053 static NTSTATUS
00054 ParPortIoctlInOut(IN PDEVICE_EXTENSION Pdx, IN ULONG Ioctl,
00055 IN PVOID InBuffer, IN ULONG InBufferLength,
00056 OUT PVOID OutBuffer, IN ULONG OutBufferLength)
00057 {
00058 IO_STATUS_BLOCK ioStatusBlock;
00059 NTSTATUS ntStatus;
00060 KEVENT event;
00061 PIRP irp;
00062
00063 FUNC_ENTER();
00064
00065
00066
00067
00068 DBG_IRQL( == PASSIVE_LEVEL);
00069 KeInitializeEvent(&event, NotificationEvent, FALSE);
00070
00071 ntStatus = STATUS_SUCCESS;
00072
00073
00074
00075 DBG_IRQL( == PASSIVE_LEVEL);
00076 irp = IoBuildDeviceIoControlRequest(
00077 Ioctl,
00078 Pdx->ParallelPortFdo,
00079 InBuffer,
00080 InBufferLength,
00081 OutBuffer,
00082 OutBufferLength,
00083 TRUE,
00084 &event,
00085 &ioStatusBlock
00086 );
00087
00088 if (irp)
00089 {
00090 PIO_STACK_LOCATION irpStack;
00091
00092
00093
00094 DBG_IRQL( <= DISPATCH_LEVEL);
00095 irpStack = IoGetNextIrpStackLocation(irp);
00096
00097
00098
00099
00100
00101 DBG_IRQL( <= DISPATCH_LEVEL);
00102 ObReferenceObject(Pdx->ParallelPortFileObject);
00103
00104
00105
00106
00107 irpStack->FileObject = Pdx->ParallelPortFileObject;
00108
00109
00110
00111 DBG_IRQL( <= DISPATCH_LEVEL);
00112 ntStatus = IoCallDriver(Pdx->ParallelPortFdo, irp);
00113
00114
00115
00116 DBG_IRQL( <= DISPATCH_LEVEL);
00117 ObDereferenceObject(Pdx->ParallelPortFileObject);
00118
00119 if (!NT_SUCCESS(ntStatus))
00120 {
00121 DBG_WARN((DBG_PREFIX "IoCallDriver FAILED!"));
00122 }
00123 else
00124 {
00125
00126
00127 DBG_IRQL( <= DISPATCH_LEVEL );
00128 ntStatus = KeWaitForSingleObject(
00129 &event,
00130 Executive,
00131 KernelMode,
00132 FALSE,
00133 NULL);
00134
00135 if (!NT_SUCCESS(ntStatus))
00136 {
00137 DBG_WARN((DBG_PREFIX "KeWaitForSingleObject FAILED!"));
00138 }
00139 }
00140 }
00141
00142 FUNC_LEAVE_NTSTATUS(ntStatus);
00143 }
00144
00157 NTSTATUS
00158 ParPortAllocate(PDEVICE_EXTENSION Pdx)
00159 {
00160 NTSTATUS ntStatus;
00161
00162 FUNC_ENTER();
00163
00164 DBG_ASSERT(Pdx);
00165 DBG_ASSERT(Pdx->ParallelPortAllocated == FALSE);
00166
00167
00168
00169 ntStatus = ParPortIoctlInOut(Pdx, IOCTL_INTERNAL_PARALLEL_PORT_ALLOCATE,
00170 NULL, 0, NULL, 0);
00171
00172
00173
00174 if (NT_SUCCESS(ntStatus))
00175 {
00176 Pdx->ParallelPortAllocated = TRUE;
00177 }
00178
00179 FUNC_LEAVE_NTSTATUS(ntStatus);
00180 }
00181
00195 NTSTATUS
00196 ParPortFree(PDEVICE_EXTENSION Pdx)
00197 {
00198 NTSTATUS ntStatus = STATUS_SUCCESS;
00199
00200 FUNC_ENTER();
00201
00202 DBG_IRQL( == PASSIVE_LEVEL);
00203
00204 DBG_ASSERT(Pdx != NULL);
00205
00206 if (Pdx->ParallelPortAllocated == TRUE)
00207 {
00208
00209
00210
00211
00212
00213
00214
00215
00216 #if 1
00217 Pdx->PortInfo->FreePort(Pdx->PortInfo->Context);
00218 #else
00219 #error THIS IS ONLY AVAILABLE ON WDM! Thus, don't use it! (see comment above)
00220 ntStatus = ParPortIoctlInOut(Pdx, IOCTL_INTERNAL_PARALLEL_PORT_FREE,
00221 NULL, 0, NULL, 0);
00222 #endif
00223
00224 Pdx->ParallelPortAllocated = FALSE;
00225 }
00226
00227 FUNC_LEAVE_NTSTATUS(ntStatus);
00228
00229 }
00230
00253 NTSTATUS
00254 ParPortInit(PUNICODE_STRING ParallelPortName, PDEVICE_EXTENSION Pdx)
00255 {
00256 NTSTATUS ntStatus;
00257
00258 FUNC_ENTER();
00259
00260 DBG_ASSERT(ParallelPortName);
00261 DBG_ASSERT(Pdx);
00262
00263
00264
00265 DBG_IRQL( == PASSIVE_LEVEL);
00266 ntStatus = IoGetDeviceObjectPointer(ParallelPortName,
00267 FILE_READ_ATTRIBUTES,
00268 &Pdx->ParallelPortFileObject,
00269 &Pdx->ParallelPortFdo);
00270
00271 if (!NT_SUCCESS(ntStatus))
00272 {
00273 DBG_WARN((DBG_PREFIX "IoGetDeviceObjectPointer() FAILED!"));
00274 FUNC_LEAVE_NTSTATUS(ntStatus);
00275 }
00276
00277
00278
00279 DBG_IRQL( == PASSIVE_LEVEL);
00280 Pdx->PortInfo = (PPARALLEL_PORT_INFORMATION) ExAllocatePoolWithTag(NonPagedPool,
00281 sizeof(*Pdx->PortInfo), MTAG_PPINFO);
00282
00283
00284
00285 if (Pdx->PortInfo)
00286 {
00287 ntStatus = ParPortIoctlInOut(Pdx, IOCTL_INTERNAL_GET_PARALLEL_PORT_INFO,
00288 NULL, 0,
00289 Pdx->PortInfo, sizeof(*Pdx->PortInfo));
00290 }
00291 else
00292 {
00293 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
00294 }
00295
00296 if (NT_SUCCESS(ntStatus))
00297 {
00298 Pdx->ParPortPortAddress = Pdx->PortInfo->Controller;
00299 DBG_PPORT((DBG_PREFIX "Got parallel port information:"));
00300 DBG_PPORT((DBG_PREFIX "- OriginalController = 0x%p", Pdx->PortInfo->OriginalController));
00301 DBG_PPORT((DBG_PREFIX "- Controller = 0x%p", Pdx->PortInfo->Controller));
00302 DBG_PPORT((DBG_PREFIX "- Span of controller = 0x%08x", Pdx->PortInfo->SpanOfController));
00303 DBG_PPORT((DBG_PREFIX "- TryAllocatePort = 0x%p", Pdx->PortInfo->TryAllocatePort));
00304 DBG_PPORT((DBG_PREFIX "- FreePort = 0x%p", Pdx->PortInfo->FreePort));
00305 DBG_PPORT((DBG_PREFIX "- QueryNumWaiters = 0x%p", Pdx->PortInfo->QueryNumWaiters));
00306 DBG_PPORT((DBG_PREFIX "- Context = 0x%p", Pdx->PortInfo->Context));
00307 }
00308
00309
00310
00311
00312 if (!NT_SUCCESS(ntStatus) && Pdx->PortInfo)
00313 {
00314 DBG_IRQL( < DISPATCH_LEVEL);
00315 ExFreePool(Pdx->PortInfo);
00316 Pdx->PortInfo = NULL;
00317 }
00318
00319 FUNC_LEAVE_NTSTATUS(ntStatus);
00320 }
00321
00339 NTSTATUS
00340 ParPortDeinit(PDEVICE_EXTENSION Pdx)
00341 {
00342 FUNC_ENTER();
00343
00344 DBG_IRQL( <= DISPATCH_LEVEL);
00345
00346
00347
00348
00349
00350 if (Pdx->ParallelPortFileObject)
00351 {
00352 DBG_IRQL( <= DISPATCH_LEVEL);
00353 ObDereferenceObject(Pdx->ParallelPortFileObject);
00354 Pdx->ParallelPortFileObject = NULL;
00355 }
00356
00357
00358
00359 if (Pdx->PortInfo)
00360 {
00361 DBG_IRQL( < DISPATCH_LEVEL);
00362 ExFreePool(Pdx->PortInfo);
00363 Pdx->PortInfo = NULL;
00364 }
00365
00366 FUNC_LEAVE_NTSTATUS_CONST(STATUS_SUCCESS);
00367 }
00368
00370 #define DBG_PPORT_VERBOSE( _yy, _xxx, _type) \
00371 DBG_PPORT((DBG_PREFIX " --- " #_xxx " = " _type, PnpInfo->_xxx))
00372
00389 static BOOLEAN
00390 ParPortGetPnpInformation(PDEVICE_EXTENSION Pdx, PPARALLEL_PNP_INFORMATION PnpInfo)
00391 {
00392 NTSTATUS ntStatus;
00393 BOOLEAN success;
00394
00395 FUNC_ENTER();
00396
00397
00398
00399 ntStatus = ParPortIoctlInOut(Pdx, IOCTL_INTERNAL_GET_PARALLEL_PNP_INFO,
00400 NULL, 0, PnpInfo, sizeof(*PnpInfo));
00401
00402 if (!NT_SUCCESS(ntStatus))
00403 {
00404
00405
00406
00407 DBG_WARN((DBG_PREFIX "IOCTL_INTERNAL_GET_PARALLEL_PNP_INFO FAILED with %s", DebugNtStatus(ntStatus)));
00408
00409 success = FALSE;
00410 }
00411 else
00412 {
00413 success = TRUE;
00414
00415
00416
00417 DBG_PPORT((DBG_PREFIX "IOCTL_INTERNAL_GET_PARALLEL_PNP_INFO:"));
00418 DBG_PPORT((DBG_PREFIX "EcpController = 0x%p", PnpInfo->EcpController));
00419
00420 DBG_PPORT_VERBOSE(PHYSICAL_ADDRESS, OriginalEcpController, "0x%p");
00421 DBG_PPORT_VERBOSE(PUCHAR, EcpController, "0x%p");
00422 DBG_PPORT_VERBOSE(ULONG, SpanOfEcpController, "%u");
00423 DBG_PPORT_VERBOSE(ULONG, PortNumber, "%u (deprecated, do not use!)");
00424 DBG_PPORT_VERBOSE(ULONG, HardwareCapabilities, "%u");
00425 DBG_PPORT_VERBOSE(PPARALLEL_SET_CHIP_MODE, TrySetChipMode, "0x%p");
00426 DBG_PPORT_VERBOSE(PPARALLEL_CLEAR_CHIP_MODE, ClearChipMode, "0x%p");
00427 DBG_PPORT_VERBOSE(ULONG, FifoDepth, "%u");
00428 DBG_PPORT_VERBOSE(ULONG, FifoWidth, "%u");
00429 DBG_PPORT_VERBOSE(PHYSICAL_ADDRESS, EppControllerPhysicalAddress, "0x%p");
00430 DBG_PPORT_VERBOSE(ULONG, SpanOfEppController, "%u");
00431 DBG_PPORT_VERBOSE(ULONG, Ieee1284_3DeviceCount, "%u");
00432 DBG_PPORT_VERBOSE(PPARALLEL_TRY_SELECT_ROUTINE, TrySelectDevice, "0x%p");
00433 DBG_PPORT_VERBOSE(PPARALLEL_DESELECT_ROUTINE, DeselectDevice, "0x%p");
00434 DBG_PPORT_VERBOSE(PVOID, Context, "0x%p");
00435 DBG_PPORT_VERBOSE(ULONG, CurrentMode, "0x%04x");
00436 DBG_PPORT_VERBOSE(PWSTR, PortName, "%ws")
00437 }
00438
00439 FUNC_LEAVE_BOOLEAN(success);
00440 }
00441 #undef DBG_PPORT_VERBOSE
00442
00455 NTSTATUS
00456 ParPortSetModeWdm(PDEVICE_EXTENSION Pdx)
00457 {
00458 PARALLEL_PNP_INFORMATION pnpInformation;
00459 NTSTATUS ntStatus;
00460
00461 FUNC_ENTER();
00462
00463
00464
00465 ntStatus = STATUS_INVALID_PARAMETER;
00466
00467 if (ParPortGetPnpInformation(Pdx, &pnpInformation))
00468 {
00469 #if DBG
00470 PUCHAR ecr;
00471
00472 if (pnpInformation.EcpController != 0)
00473 {
00474 ecr = pnpInformation.EcpController + ECR_OFFSET;
00475
00476 DBG_PPORT((DBG_PREFIX "We're having an ECP controller: ECR = %08x", ecr));
00477 DBG_PPORT((DBG_PREFIX " --- ECR = %02x", READ_PORT_UCHAR(ecr)));
00478 }
00479 #endif
00480
00481
00482
00483
00484
00485 if (pnpInformation.TrySetChipMode && pnpInformation.ClearChipMode)
00486 {
00487
00488
00489
00490 if (pnpInformation.HardwareCapabilities & PPT_BYTE_PRESENT)
00491 {
00492 DBG_PPORT((DBG_PREFIX "Trying to set Chip mode to BYTE MODE..."));
00493
00494
00495
00496 DBG_IRQL( <= DISPATCH_LEVEL);
00497 ntStatus = pnpInformation.TrySetChipMode(pnpInformation.Context, ECR_BYTE_MODE);
00498
00499 DBG_PPORT((DBG_PREFIX " --- TrySetChipMode returned with %s", DebugNtStatus(ntStatus)));
00500 }
00501 else
00502 {
00503
00504
00505
00506 DBG_PPORT((DBG_PREFIX "****************************** NO BYTE MODE PRESENT, making sure to have SPP mode!!!"));
00507 ParPortUnsetMode(Pdx);
00508 }
00509 #if DBG
00510 if (pnpInformation.EcpController != 0)
00511 {
00512 DBG_PPORT((DBG_PREFIX " --- ECR = %02x", READ_PORT_UCHAR(ecr)));
00513 }
00514 #endif
00515 }
00516 else
00517 {
00518 DBG_PPORT((DBG_PREFIX " --- TrySetChipMode or ClearChipmode not available!"));
00519 }
00520 }
00521
00522 FUNC_LEAVE_NTSTATUS(ntStatus);
00523 }
00524
00538 NTSTATUS
00539 ParPortUnsetModeWdm(PDEVICE_EXTENSION Pdx)
00540 {
00541 PARALLEL_PNP_INFORMATION pnpInformation;
00542 NTSTATUS ntStatus;
00543
00544 FUNC_ENTER();
00545
00546
00547
00548 ntStatus = STATUS_SUCCESS;
00549
00550 if (ParPortGetPnpInformation(Pdx, &pnpInformation))
00551 {
00552 #if DBG
00553 PUCHAR ecr;
00554
00555 if (pnpInformation.EcpController != 0)
00556 {
00557 ecr = pnpInformation.EcpController + ECR_OFFSET;
00558
00559 DBG_PPORT((DBG_PREFIX "We're having an ECP controller: ECR = %08x", ecr));
00560
00561 DBG_PPORT((DBG_PREFIX " --- ECR = %02x", READ_PORT_UCHAR(ecr)));
00562 }
00563 #endif
00564
00565
00566
00567 if (pnpInformation.ClearChipMode)
00568 {
00569 DBG_PPORT((DBG_PREFIX "Trying to unset Chip mode..."));
00570
00571 DBG_IRQL( <= DISPATCH_LEVEL);
00572 ntStatus = pnpInformation.ClearChipMode(
00573 pnpInformation.Context,
00574 (UCHAR) pnpInformation.CurrentMode);
00575
00576 DBG_PPORT((DBG_PREFIX " --- ClearChipMode returned with %s", DebugNtStatus(ntStatus)));
00577
00578
00579
00580
00581
00582 if (ntStatus == STATUS_UNSUCCESSFUL)
00583 {
00584 ntStatus = STATUS_SUCCESS;
00585 }
00586 }
00587
00588 #if DBG
00589 if (pnpInformation.EcpController != 0)
00590 {
00591 DBG_PPORT((DBG_PREFIX " --- ECR = %02x", READ_PORT_UCHAR(ecr)));
00592 }
00593 #endif
00594 }
00595
00596 FUNC_LEAVE_NTSTATUS(ntStatus);
00597 }
00598
00617 NTSTATUS
00618 ParPortAllocInterrupt(PDEVICE_EXTENSION Pdx, PKSERVICE_ROUTINE Isr)
00619 {
00620 NTSTATUS ntStatus;
00621
00622 FUNC_ENTER();
00623
00624 DBG_IRQL( == PASSIVE_LEVEL);
00625
00626 DBG_ASSERT(Pdx);
00627 DBG_ASSERT(Isr);
00628 DBG_ASSERT(Pdx->ParallelPortAllocatedInterrupt == FALSE);
00629
00630 Pdx->Pisr.InterruptServiceRoutine = Isr;
00631 Pdx->Pisr.InterruptServiceContext = Pdx;
00632 Pdx->Pisr.DeferredPortCheckRoutine = NULL;
00633 Pdx->Pisr.DeferredPortCheckContext = NULL;
00634
00635
00636
00637 ntStatus = ParPortIoctlInOut(Pdx, IOCTL_INTERNAL_PARALLEL_CONNECT_INTERRUPT,
00638 &Pdx->Pisr, sizeof(Pdx->Pisr),
00639 &Pdx->Pii, sizeof(Pdx->Pii));
00640
00641
00642
00643 if (NT_SUCCESS(ntStatus))
00644 {
00645 Pdx->ParallelPortAllocatedInterrupt = TRUE;
00646 }
00647 else
00648 {
00649 DBG_WARN((DBG_PREFIX "Allocation of Interrupt FAILED!"));
00650 LogErrorOnly(Pdx->Fdo, CBM_NO_ISR);
00651 }
00652
00653 FUNC_LEAVE_NTSTATUS(ntStatus);
00654 }
00655
00669 NTSTATUS
00670 ParPortFreeInterrupt(PDEVICE_EXTENSION Pdx)
00671 {
00672 NTSTATUS ntStatus;
00673
00674 FUNC_ENTER();
00675
00676 DBG_IRQL( == PASSIVE_LEVEL);
00677
00678 DBG_ASSERT(Pdx);
00679
00680
00681
00682 if (Pdx->ParallelPortAllocatedInterrupt == TRUE)
00683 {
00684 ntStatus = ParPortIoctlInOut(Pdx, IOCTL_INTERNAL_PARALLEL_DISCONNECT_INTERRUPT,
00685 &Pdx->Pisr, sizeof(Pdx->Pisr),
00686 NULL, 0);
00687
00688 Pdx->ParallelPortAllocatedInterrupt = FALSE;
00689 }
00690 else
00691 {
00692
00693
00694
00695 ntStatus = STATUS_SUCCESS;
00696 }
00697
00698 FUNC_LEAVE_NTSTATUS(ntStatus);
00699 }
00700
00718 NTSTATUS
00719 ParPortAllowInterruptIoctl(PDEVICE_EXTENSION Pdx)
00720 {
00721 PDEVICE_OBJECT pdo;
00722 NTSTATUS ntStatus;
00723 HANDLE handleReg;
00724 ULONG OldStateEnableConnectInterruptIoctl;
00725 ULONG OldStateFilterResourceMethod;
00726
00727 FUNC_ENTER();
00728
00729 DBG_ASSERT(Pdx);
00730
00731
00732
00733 ntStatus = cbm_registry_open_hardwarekey(&handleReg, &pdo, Pdx);
00734
00735 if (NT_SUCCESS(ntStatus))
00736 {
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749 ntStatus = cbm_registry_read_ulong(handleReg, L"EnableConnectInterruptIoctl",
00750 &OldStateEnableConnectInterruptIoctl);
00751
00752
00753
00754 if (ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
00755 {
00756 OldStateEnableConnectInterruptIoctl = -1;
00757 ntStatus = STATUS_SUCCESS;
00758 }
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772 ntStatus = cbm_registry_read_ulong(handleReg, L"FilterResourceMethod",
00773 &OldStateFilterResourceMethod);
00774
00775
00776
00777 if (ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
00778 {
00779 OldStateFilterResourceMethod = -1;
00780 ntStatus = STATUS_SUCCESS;
00781 }
00782
00783
00784
00785
00786 if (NT_SUCCESS(ntStatus) && OldStateEnableConnectInterruptIoctl != 1)
00787 {
00788 ntStatus = cbm_registry_write_ulong(handleReg, L"EnableConnectInterruptIoctl", 1);
00789 }
00790
00791 if (NT_SUCCESS(ntStatus) && OldStateFilterResourceMethod != 2)
00792 {
00793 ntStatus = cbm_registry_write_ulong(handleReg, L"FilterResourceMethod", 2);
00794 }
00795
00796
00797
00798 cbm_registry_close_hardwarekey(handleReg, pdo);
00799 }
00800
00801 FUNC_LEAVE_NTSTATUS(ntStatus);
00802 }