00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00020 #include <wdm.h>
00021 #include "cbm_driver.h"
00022 #include "cbmioctl.h"
00023 #include "iec.h"
00024
00025 #include <parallel.h>
00026
00027
00045 static NTSTATUS
00046 cbm_checkinputbuffer(IN PIO_STACK_LOCATION IrpSp, USHORT Len, NTSTATUS StatusOnSuccess)
00047 {
00048 FUNC_ENTER();
00049
00050 if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < Len)
00051 {
00052 StatusOnSuccess = STATUS_BUFFER_TOO_SMALL;
00053 }
00054
00055 FUNC_LEAVE_NTSTATUS(StatusOnSuccess);
00056 }
00057
00075 static NTSTATUS
00076 cbm_checkoutputbuffer(IN PIO_STACK_LOCATION IrpSp, USHORT Len, NTSTATUS StatusOnSuccess)
00077 {
00078 FUNC_ENTER();
00079
00080 if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < Len)
00081 {
00082 StatusOnSuccess = STATUS_BUFFER_TOO_SMALL;
00083 }
00084
00085 FUNC_LEAVE_NTSTATUS(StatusOnSuccess);
00086 }
00087
00114 NTSTATUS
00115 cbm_devicecontrol(IN PDEVICE_OBJECT Fdo, IN PIRP Irp)
00116 {
00117 PPAR_SET_INFORMATION setInfo;
00118 PIO_STACK_LOCATION irpSp;
00119 PDEVICE_EXTENSION pdx;
00120 NTSTATUS ntStatus;
00121 BOOLEAN fastStart;
00122
00123 FUNC_ENTER();
00124
00125
00126
00127 pdx = Fdo->DeviceExtension;
00128
00129
00130
00131 irpSp = IoGetCurrentIrpStackLocation(Irp);
00132
00133
00134 DBG_IRPPATH_PROCESS("Ioctl");
00135
00136
00137
00138 fastStart = FALSE;
00139
00140
00141
00142
00143
00144 switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
00145
00146 case CBMCTRL_TALK:
00147 DBG_IRP(CBMCTRL_TALK);
00148 ntStatus = cbm_checkinputbuffer(irpSp, sizeof(CBMT_TALK_IN), STATUS_SUCCESS);
00149 break;
00150
00151 case CBMCTRL_LISTEN:
00152 DBG_IRP(CBMCTRL_LISTEN);
00153 ntStatus = cbm_checkinputbuffer(irpSp, sizeof(CBMT_LISTEN_IN), STATUS_SUCCESS);
00154 break;
00155
00156 case CBMCTRL_UNTALK:
00157 DBG_IRP(CBMCTRL_UNTALK);
00158 ntStatus = STATUS_SUCCESS;
00159 break;
00160
00161 case CBMCTRL_UNLISTEN:
00162 DBG_IRP(CBMCTRL_UNLISTEN);
00163 ntStatus = STATUS_SUCCESS;
00164 break;
00165
00166 case CBMCTRL_OPEN:
00167 DBG_IRP(CBMCTRL_OPEN);
00168 ntStatus = cbm_checkinputbuffer(irpSp, sizeof(CBMT_OPEN_IN), STATUS_SUCCESS);
00169 break;
00170
00171 case CBMCTRL_CLOSE:
00172 DBG_IRP(CBMCTRL_CLOSE);
00173 ntStatus = cbm_checkinputbuffer(irpSp, sizeof(CBMT_CLOSE_IN), STATUS_SUCCESS);
00174 break;
00175
00176 case CBMCTRL_RESET:
00177 DBG_IRP(CBMCTRL_RESET);
00178 ntStatus = STATUS_SUCCESS;
00179 break;
00180
00181 case CBMCTRL_GET_EOI:
00182 DBG_IRP(CBMCTRL_GET_EOI);
00183 ntStatus = cbm_checkoutputbuffer(irpSp, sizeof(CBMT_GET_EOI_OUT), STATUS_SUCCESS);
00184 fastStart = TRUE;
00185 break;
00186
00187 case CBMCTRL_CLEAR_EOI:
00188 DBG_IRP(CBMCTRL_CLEAR_EOI);
00189 ntStatus = STATUS_SUCCESS;
00190 fastStart = TRUE;
00191 break;
00192
00193 case CBMCTRL_PP_READ:
00194 DBG_IRP(CBMCTRL_PP_READ);
00195 ntStatus = cbm_checkoutputbuffer(irpSp, sizeof(CBMT_PP_READ_OUT), STATUS_SUCCESS);
00196 fastStart = TRUE;
00197 break;
00198
00199 case CBMCTRL_PP_WRITE:
00200 DBG_IRP(CBMCTRL_PP_WRITE);
00201 ntStatus = cbm_checkinputbuffer(irpSp, sizeof(CBMT_PP_WRITE_IN), STATUS_SUCCESS);
00202 fastStart = TRUE;
00203 break;
00204
00205 case CBMCTRL_IEC_POLL:
00206 DBG_IRP(CBMCTRL_IEC_POLL);
00207 ntStatus = cbm_checkoutputbuffer(irpSp, sizeof(CBMT_IEC_POLL_OUT), STATUS_SUCCESS);
00208 fastStart = TRUE;
00209 break;
00210
00211 case CBMCTRL_IEC_SET:
00212 DBG_IRP(CBMCTRL_IEC_SET);
00213 ntStatus = cbm_checkinputbuffer(irpSp, sizeof(CBMT_IEC_SET_IN), STATUS_SUCCESS);
00214 fastStart = TRUE;
00215 break;
00216
00217 case CBMCTRL_IEC_RELEASE:
00218 DBG_IRP(CBMCTRL_IEC_RELEASE);
00219 ntStatus = cbm_checkinputbuffer(irpSp, sizeof(CBMT_IEC_RELEASE_IN), STATUS_SUCCESS);
00220 fastStart = TRUE;
00221 break;
00222
00223 case CBMCTRL_IEC_SETRELEASE:
00224 DBG_IRP(CBMCTRL_IEC_SETRELEASE);
00225 ntStatus = cbm_checkinputbuffer(irpSp, sizeof(CBMT_IEC_SETRELEASE_IN), STATUS_SUCCESS);
00226 fastStart = TRUE;
00227 break;
00228
00229 case CBMCTRL_IEC_WAIT:
00230 DBG_IRP(CBMCTRL_IEC_WAIT);
00231 ntStatus = cbm_checkoutputbuffer(irpSp, sizeof(CBMT_IEC_WAIT_OUT),
00232 cbm_checkinputbuffer(irpSp, sizeof(CBMT_IEC_WAIT_IN), STATUS_SUCCESS));
00233 break;
00234
00235 case CBMCTRL_PARBURST_READ:
00236 DBG_IRP(CBMCTRL_PARBURST_READ);
00237 ntStatus = cbm_checkoutputbuffer(irpSp, sizeof(CBMT_PARBURST_PREAD_OUT), STATUS_SUCCESS);
00238 break;
00239
00240 case CBMCTRL_PARBURST_WRITE:
00241 DBG_IRP(CBMCTRL_PARBURST_WRITE);
00242 ntStatus = cbm_checkinputbuffer(irpSp, sizeof(CBMT_PARBURST_PWRITE_IN), STATUS_SUCCESS);
00243 break;
00244
00245 case CBMCTRL_PARBURST_READ_TRACK:
00246 DBG_IRP(CBMCTRL_PARBURST_READ_TRACK);
00247 ntStatus = cbm_checkoutputbuffer(irpSp, 1, STATUS_SUCCESS);
00248 break;
00249
00250 case CBMCTRL_PARBURST_WRITE_TRACK:
00251 DBG_IRP(CBMCTRL_PARBURST_WRITE_TRACK);
00252 ntStatus = cbm_checkinputbuffer(irpSp, 1, STATUS_SUCCESS);
00253 break;
00254
00255 case CBMCTRL_I_INSTALL:
00256 DBG_IRP(CBMCTRL_I_INSTALL);
00257 ntStatus = cbm_checkoutputbuffer(irpSp, sizeof(CBMT_I_INSTALL_OUT), STATUS_SUCCESS);
00258 break;
00259
00260 case CBMCTRL_PARPORT_LOCK:
00261 DBG_IRP(CBMCTRL_PARPORT_LOCK);
00262 ntStatus = STATUS_SUCCESS;
00263 break;
00264
00265 case CBMCTRL_PARPORT_UNLOCK:
00266 DBG_IRP(CBMCTRL_PARPORT_UNLOCK);
00267 ntStatus = STATUS_SUCCESS;
00268 break;
00269
00270 case CBMCTRL_UPDATE:
00271 DBG_IRP(CBMCTRL_UPDATE);
00272 ntStatus = STATUS_SUCCESS;
00273 fastStart = TRUE;
00274 break;
00275
00276 #if DBG
00277
00278 case CBMCTRL_I_READDBG:
00279 DBG_IRP(CBMCTRL_I_READDBG);
00280 ntStatus = cbm_checkoutputbuffer(irpSp, sizeof(CHAR), STATUS_SUCCESS);
00281 break;
00282
00283 #endif // #if DBG
00284
00285 default:
00286 DBG_ERROR((DBG_PREFIX "unknown IRP_MJ_DEVICE_CONTROL"));
00287 ntStatus = STATUS_INVALID_PARAMETER;
00288 break;
00289 }
00290
00291 if (NT_SUCCESS(ntStatus))
00292 {
00293 PERF_EVENT_IOCTL_QUEUE(irpSp->Parameters.DeviceIoControl.IoControlCode);
00294
00295
00296
00297
00298
00299 ntStatus = QueueStartPacket(&pdx->IrpQueue, Irp, fastStart, Fdo);
00300 }
00301 else
00302 {
00303
00304
00305
00306 QueueCompleteIrp(NULL, Irp, ntStatus, 0);
00307 }
00308
00309 FUNC_LEAVE_NTSTATUS(ntStatus);
00310 }
00311
00315 #define INPUTVALUE(_ttt_) ((_ttt_ *) Irp->AssociatedIrp.SystemBuffer)
00316
00320 #define OUTPUTVALUE(_ttt_) ((_ttt_ *) Irp->AssociatedIrp.SystemBuffer)
00321
00341 NTSTATUS
00342 cbm_execute_devicecontrol(IN PDEVICE_EXTENSION Pdx, IN PIRP Irp)
00343 {
00344 PPAR_SET_INFORMATION setInfo;
00345 PIO_STACK_LOCATION irpSp;
00346 ULONG_PTR returnLength;
00347 NTSTATUS ntStatus;
00348
00349 FUNC_ENTER();
00350
00351
00352
00353
00354
00355 returnLength = 0;
00356
00357
00358
00359 irpSp = IoGetCurrentIrpStackLocation(Irp);
00360
00361 PERF_EVENT_IOCTL_EXECUTE(irpSp->Parameters.DeviceIoControl.IoControlCode);
00362
00363 DBG_IRPPATH_EXECUTE("Execute Ioctl");
00364
00365
00366
00367
00368
00369 switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
00370
00371 case CBMCTRL_TALK:
00372 DBG_IRP(CBMCTRL_TALK);
00373 ntStatus = cbmiec_talk(Pdx, INPUTVALUE(CBMT_TALK_IN)->PrimaryAddress & 0x1F,
00374 INPUTVALUE(CBMT_TALK_IN)->SecondaryAddress);
00375 break;
00376
00377 case CBMCTRL_LISTEN:
00378 DBG_IRP(CBMCTRL_LISTEN);
00379 ntStatus = cbmiec_listen(Pdx, INPUTVALUE(CBMT_LISTEN_IN)->PrimaryAddress & 0x1F,
00380 INPUTVALUE(CBMT_LISTEN_IN)->SecondaryAddress);
00381 break;
00382
00383 case CBMCTRL_UNTALK:
00384 DBG_IRP(CBMCTRL_UNTALK);
00385 ntStatus = cbmiec_untalk(Pdx);
00386 break;
00387
00388 case CBMCTRL_UNLISTEN:
00389 DBG_IRP(CBMCTRL_UNLISTEN);
00390 ntStatus = cbmiec_unlisten(Pdx);
00391 break;
00392
00393 case CBMCTRL_OPEN:
00394 DBG_IRP(CBMCTRL_OPEN);
00395 ntStatus = cbmiec_open(Pdx, INPUTVALUE(CBMT_OPEN_IN)->PrimaryAddress & 0x1F,
00396 INPUTVALUE(CBMT_OPEN_IN)->SecondaryAddress);
00397 break;
00398
00399 case CBMCTRL_CLOSE:
00400 DBG_IRP(CBMCTRL_CLOSE);
00401 ntStatus = cbmiec_close(Pdx,INPUTVALUE(CBMT_CLOSE_IN)->PrimaryAddress & 0x1F,
00402 INPUTVALUE(CBMT_CLOSE_IN)->SecondaryAddress);
00403 break;
00404
00405 case CBMCTRL_RESET:
00406 DBG_IRP(CBMCTRL_RESET);
00407 ntStatus = cbmiec_reset(Pdx);
00408 break;
00409
00410 case CBMCTRL_GET_EOI:
00411 DBG_IRP(CBMCTRL_GET_EOI);
00412 returnLength = sizeof(CBMT_GET_EOI_OUT);
00413 ntStatus = cbmiec_get_eoi(Pdx, &(OUTPUTVALUE(CBMT_GET_EOI_OUT)->Decision));
00414 break;
00415
00416 case CBMCTRL_CLEAR_EOI:
00417 DBG_IRP(CBMCTRL_CLEAR_EOI);
00418 ntStatus = cbmiec_clear_eoi(Pdx);
00419 break;
00420
00421 case CBMCTRL_PP_READ:
00422 DBG_IRP(CBMCTRL_PP_READ);
00423 ntStatus = cbm_checkoutputbuffer(irpSp, sizeof(CBMT_PP_READ_OUT), STATUS_SUCCESS);
00424 returnLength = sizeof(CBMT_PP_READ_OUT);
00425 ntStatus = cbmiec_pp_read(Pdx, &(OUTPUTVALUE(CBMT_PP_READ_OUT)->Byte));
00426 break;
00427
00428 case CBMCTRL_PP_WRITE:
00429 DBG_IRP(CBMCTRL_PP_WRITE);
00430 ntStatus = cbmiec_pp_write(Pdx, INPUTVALUE(CBMT_PP_WRITE_IN)->Byte);
00431 break;
00432
00433 case CBMCTRL_IEC_POLL:
00434 DBG_IRP(CBMCTRL_IEC_POLL);
00435 returnLength = sizeof(CBMT_IEC_POLL_OUT);
00436 ntStatus = cbmiec_iec_poll(Pdx, &(OUTPUTVALUE(CBMT_IEC_POLL_OUT)->Line));
00437 break;
00438
00439 case CBMCTRL_IEC_SET:
00440 DBG_IRP(CBMCTRL_IEC_SET);
00441 ntStatus = cbmiec_iec_set(Pdx, INPUTVALUE(CBMT_IEC_SET_IN)->Line);
00442 break;
00443
00444 case CBMCTRL_IEC_RELEASE:
00445 DBG_IRP(CBMCTRL_IEC_RELEASE);
00446 ntStatus = cbmiec_iec_release(Pdx, INPUTVALUE(CBMT_IEC_RELEASE_IN)->Line);
00447 break;
00448
00449 case CBMCTRL_IEC_SETRELEASE:
00450 DBG_IRP(CBMCTRL_IEC_SETRELEASE);
00451 ntStatus = cbmiec_iec_setrelease(Pdx,
00452 INPUTVALUE(CBMT_IEC_SETRELEASE_IN)->State,
00453 INPUTVALUE(CBMT_IEC_SETRELEASE_IN)->Line);
00454 break;
00455
00456 case CBMCTRL_IEC_WAIT:
00457 DBG_IRP(CBMCTRL_IEC_WAIT);
00458 returnLength = sizeof(CBMT_IEC_WAIT_OUT);
00459 ntStatus = cbmiec_iec_wait(Pdx, INPUTVALUE(CBMT_IEC_WAIT_IN)->Line,
00460 INPUTVALUE(CBMT_IEC_WAIT_IN)->State,
00461 &(OUTPUTVALUE(CBMT_IEC_WAIT_OUT)->Line));
00462 break;
00463
00464 case CBMCTRL_PARBURST_READ:
00465 DBG_IRP(CBMCTRL_PARBURST_READ);
00466 returnLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
00467 ntStatus = cbmiec_parallel_burst_read(Pdx, &(OUTPUTVALUE(CBMT_PARBURST_PREAD_OUT)->Byte));
00468 break;
00469
00470 case CBMCTRL_PARBURST_WRITE:
00471 DBG_IRP(CBMCTRL_PARBURST_READ);
00472 returnLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
00473 ntStatus = cbmiec_parallel_burst_write(Pdx, INPUTVALUE(CBMT_PARBURST_PWRITE_IN)->Byte);
00474 break;
00475
00476 case CBMCTRL_PARBURST_READ_TRACK:
00477 DBG_IRP(CBMCTRL_PARBURST_READ_TRACK);
00478 returnLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
00479 ntStatus = cbmiec_parallel_burst_read_track(Pdx,
00480 Irp->AssociatedIrp.SystemBuffer, (ULONG) returnLength);
00481 break;
00482
00483 case CBMCTRL_PARBURST_WRITE_TRACK:
00484 DBG_IRP(CBMCTRL_PARBURST_WRITE_TRACK);
00485 returnLength = irpSp->Parameters.DeviceIoControl.InputBufferLength;
00486 ntStatus = cbmiec_parallel_burst_write_track(Pdx,
00487 Irp->AssociatedIrp.SystemBuffer, (ULONG) returnLength);
00488 break;
00489
00490 case CBMCTRL_I_INSTALL:
00491 DBG_IRP(CBMCTRL_I_INSTALL);
00492 returnLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
00493 ntStatus = cbm_install(Pdx, OUTPUTVALUE(CBMT_I_INSTALL_OUT), (PULONG) &returnLength);
00494 break;
00495
00496 case CBMCTRL_PARPORT_LOCK:
00497 DBG_IRP(CBMCTRL_PARPORT_LOCK);
00498 ntStatus = cbm_lock(Pdx);
00499 break;
00500
00501 case CBMCTRL_PARPORT_UNLOCK:
00502 DBG_IRP(CBMCTRL_PARPORT_UNLOCK);
00503 ntStatus = cbm_unlock(Pdx);
00504 break;
00505
00506 case CBMCTRL_UPDATE:
00507 DBG_IRP(CBMCTRL_UPDATE);
00508 cbm_init_registry(NULL, Pdx);
00509 ntStatus = STATUS_SUCCESS;
00510 break;
00511
00512 #if DBG
00513
00514 case CBMCTRL_I_READDBG:
00515 DBG_IRP(CBMCTRL_I_READDBG);
00516 returnLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
00517 ntStatus = cbm_dbg_readbuffer(Pdx, OUTPUTVALUE(CHAR), (PULONG) &returnLength);
00518 break;
00519
00520 #endif // #if DBG
00521
00522 default:
00523
00524
00525
00526
00527
00528 DBG_ERROR((DBG_PREFIX "unknown IRP_MJ_DEVICE_CONTROL"));
00529 DBG_ASSERT(("THIS SHOULD NOT HAPPEN!", 0));
00530 ntStatus = STATUS_INVALID_PARAMETER;
00531 break;
00532 }
00533
00534
00535
00536 if (!NT_SUCCESS(ntStatus))
00537 {
00538 returnLength = 0;
00539 }
00540
00541
00542
00543 DBG_IRPPATH_COMPLETE("Execute Ioctl");
00544 QueueCompleteIrp(&Pdx->IrpQueue, Irp, ntStatus, returnLength);
00545
00546 FUNC_LEAVE_NTSTATUS(ntStatus);
00547 }