00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00023 #include <initguid.h>
00024 #include <wdm.h>
00025 #include "cbm_driver.h"
00026
00027
00028
00029
00030
00031 #define AdvancedEPPTests 1
00032
00033 enum lptMode
00034 {
00035 lptN_A = 0,
00036 lptSPP = 1,
00037 lptPS2 = 2,
00038 lptEPP = 3,
00039 lptECP = 4,
00040 lptEPPc = 5,
00041 };
00042
00043 enum ecpMode
00044 {
00045 ecpNOECR = 0,
00046
00047 ecpSTNDRD = 1,
00048 ecpBYTE = 2,
00049 ecpSTDFIFO = 3,
00050 ecpECPFIFO = 4,
00051 ecpEPP = 5,
00052 ecpRESVRD = 6,
00053 ecpFIFOTST = 7,
00054 ecpCONFIG = 8
00055 };
00056
00057
00058 static void
00059 BIDIoutp(PUCHAR port)
00060 {
00061 WRITE_PORT_UCHAR(port+2,0xC4);
00062 }
00063
00064
00065 static void
00066 BIDIinp(PUCHAR port)
00067 {
00068 WRITE_PORT_UCHAR(port+2,0xE4);
00069 }
00070
00071
00072 static void
00073 EPPclear(PUCHAR port)
00074 {
00075 unsigned char val=READ_PORT_UCHAR(port+1);
00076
00077
00078 WRITE_PORT_UCHAR(port+1,val|0x01);
00079 WRITE_PORT_UCHAR(port+1,val&0xFE);
00080 }
00081
00082
00083
00084
00085
00086
00087 static enum lptMode
00088 ECPdetect(PUCHAR port)
00089 {
00090 enum lptMode ret = lptN_A;
00091
00092 unsigned char ECR = READ_PORT_UCHAR(port+0x402)&~0x07;
00093 do
00094 {
00095 WRITE_PORT_UCHAR(port+0x402,0x34);
00096 WRITE_PORT_UCHAR(port+2,0xC6);
00097 if(READ_PORT_UCHAR(port+0x402)!=0x35){
00098 ECR=0xC4;
00099 break;
00100 }
00101
00102 WRITE_PORT_UCHAR(port+0x402,0x35);
00103 WRITE_PORT_UCHAR(port+0x402,0xd4);
00104 READ_PORT_UCHAR(port+0x400);
00105 WRITE_PORT_UCHAR(port+0x400,0xAA);
00106 if(READ_PORT_UCHAR(port+0x400)!=0xAA)
00107 break;
00108
00109 WRITE_PORT_UCHAR(port+0x400,0x55);
00110 if(READ_PORT_UCHAR(port+0x400)!=0x55)
00111 break;
00112
00113 ret=lptECP;
00114
00115 } while(0);
00116
00117 WRITE_PORT_UCHAR(port+0x402,0x35);
00118 WRITE_PORT_UCHAR(port+0x402,ECR);
00119 return ret;
00120 }
00121
00122
00123 static enum lptMode
00124 EPPdWOC(PUCHAR port)
00125 {
00126 do
00127 {
00128 EPPclear(port);
00129 WRITE_PORT_UCHAR(port+3,0xAA);
00130 EPPclear(port);
00131 if(READ_PORT_UCHAR(port+3)!=0xAA)
00132 break;
00133
00134 EPPclear(port);
00135 WRITE_PORT_UCHAR(port+3,0x55);
00136 EPPclear(port);
00137
00138 if(READ_PORT_UCHAR(port+3)!=0x55)
00139 break;
00140
00141 return lptEPP;
00142
00143 } while(0);
00144
00145 EPPclear(port);
00146 WRITE_PORT_UCHAR(port+3,0x00);
00147 READ_PORT_UCHAR(port+3);
00148
00149 if(!(READ_PORT_UCHAR(port+1)&0x01))
00150 return lptN_A;
00151
00152 EPPclear(port);
00153 if(READ_PORT_UCHAR(port+1)&0x01)
00154 return lptN_A;
00155
00156 return lptEPP;
00157 }
00158
00159
00160
00161
00162 static enum lptMode
00163 EPPdetect(PUCHAR port)
00164 {
00165 WRITE_PORT_UCHAR(port+2, (UCHAR) 0xEF);
00166 return EPPdWOC(port);
00167 }
00168
00169
00170 static enum lptMode
00171 PPPdetect(PUCHAR port)
00172 {
00173 BIDIoutp(port);
00174
00175 WRITE_PORT_UCHAR(port,0xAA);
00176 if(READ_PORT_UCHAR(port)!=0xAA)
00177 return lptN_A;
00178
00179 WRITE_PORT_UCHAR(port,0x55);
00180 if(READ_PORT_UCHAR(port)!=0x55)
00181 return lptN_A;
00182
00183 BIDIinp(port);
00184
00185 WRITE_PORT_UCHAR(port,0xAA);
00186 if(READ_PORT_UCHAR(port)!=0xAA)
00187 return lptPS2;
00188
00189 WRITE_PORT_UCHAR(port,0x55);
00190 if(READ_PORT_UCHAR(port)!=0x55)
00191 return lptPS2;
00192
00193 return lptSPP;
00194 }
00195
00196
00197 static void
00198 ResetLPT(PUCHAR port)
00199 {
00200 int i;
00201
00202
00203
00204
00205
00206
00207 for(i=10;i>0;i--)
00208 WRITE_PORT_UCHAR(port+2,0xC0);
00209
00210 BIDIoutp(port);
00211 }
00212
00213
00214
00215
00216
00217 #if AdvancedEPPTests
00218 enum lptMode AdvEPP(PUCHAR port){
00219 unsigned char EPPctrl=0;
00220
00221
00222 do
00223 {
00224 EPPctrl |= 0x04;
00225
00226 WRITE_PORT_UCHAR(port+2,EPPctrl);
00227
00228 if (EPPdWOC(port)!=lptN_A)
00229 return lptEPPc;
00230
00231 EPPctrl++;
00232 } while(EPPctrl);
00233
00234 return lptN_A;
00235 }
00236
00237
00238 static char *
00239 EPPcontrol(PUCHAR port){
00240 int ret;
00241 static char ctrlWord[8];
00242 unsigned int done0[8], done1[8];
00243 unsigned char i,EPPctrl, OldCtrl,mask;
00244
00245 for (i=0;i<8;i++)
00246 done0[i]=done1[i]=0;
00247
00248 OldCtrl = READ_PORT_UCHAR(port+2)&0x1f;
00249 EPPctrl = 0;
00250
00251 do
00252 {
00253 EPPctrl|=0x04;
00254
00255 WRITE_PORT_UCHAR(port+2,EPPctrl);
00256 if(EPPdWOC(port)!=lptN_A)
00257 {
00258
00259
00260 for(i=0,mask=0x80;i<8;i++,mask>>=1)
00261 {
00262 if(EPPctrl&mask)
00263 done1[i]++;
00264 else
00265 done0[i]++;
00266 }
00267 }
00268 EPPctrl++;
00269 } while(EPPctrl);
00270
00271 WRITE_PORT_UCHAR(port+2,OldCtrl);
00272
00273 for (i=0;i<8;i++)
00274 {
00275 if(done0[i]==done1[i])
00276 {
00277 if(!done0[i]) ctrlWord[i]='!';
00278 else ctrlWord[i]='X';
00279 }
00280 else if(!done0[i]) ctrlWord[i]='1';
00281 else if(!done1[i]) ctrlWord[i]='0';
00282 else ctrlWord[i]='?';
00283 }
00284 return ctrlWord;
00285 }
00286 #else
00287 static char *
00288 EPPcontrol(PUCHAR)
00289 {
00290 return "XX0X0100";
00291 }
00292 #endif
00293
00294 static enum lptMode
00295 LPTmode(PUCHAR port)
00296 {
00297 enum lptMode ret=lptN_A;
00298
00299
00300
00301
00302 if((((ULONG_PTR)port) & ~0x1fc)!=0x200)
00303 return lptN_A;
00304
00305
00306
00307
00308 ResetLPT(port);
00309
00310
00311 do
00312 {
00313
00314 if((ret = ECPdetect(port)) != lptN_A)
00315 break;
00316
00317
00318 ResetLPT(port);
00319
00320
00321 if ((ret = EPPdetect(port)) != lptN_A)
00322 break;
00323
00324 #if AdvancedEPPTests
00325
00326 if ((ret = AdvEPP(port)) != lptN_A)
00327 break;
00328 #endif
00329
00330 if ((ret = PPPdetect(port)) != lptN_A)
00331 break;
00332
00333 } while(0);
00334 BIDIoutp(port);
00335 return ret;
00336 }
00337
00338 static enum ecpMode
00339 ECPmode(PUCHAR port)
00340 {
00341 if (LPTmode(port) != lptECP)
00342 return ecpNOECR;
00343
00344 return (enum ecpMode)(ecpSTNDRD + (READ_PORT_UCHAR(port+0x402)>>5));
00345 }
00346
00347 static enum ecpMode
00348 SetECPmode(PUCHAR port, enum ecpMode mode)
00349 {
00350 unsigned char oldvalue;
00351
00352 if (LPTmode(port) != lptECP)
00353 return ecpNOECR;
00354
00355 oldvalue = READ_PORT_UCHAR(port+0x402);
00356
00357 WRITE_PORT_UCHAR(port+0x402, (oldvalue & 0x3f) | ((mode - ecpSTNDRD) << 5));
00358
00359 return (enum ecpMode)(ecpSTNDRD + (oldvalue>>5));
00360 }
00361
00362
00363
00364
00365
00366 static int
00367 preprprt(PUCHAR port)
00368 {
00369 enum lptMode mode;
00370 const char *modes[6]={"N/A","SPP","PS/2","EPP","ECP","EPPc"};
00371
00372 FUNC_ENTER();
00373
00374 mode=LPTmode(port);
00375 DBG_PRINT((DBG_PREFIX "at 0x%03X, %s", port, modes[mode]));
00376
00377 FUNC_LEAVE_INT(mode);
00378 }
00379
00380 static int
00381 prport(PUCHAR port)
00382 {
00383 const char *ecpM[9]={
00384 "no ECR found",
00385 "Standard Mode",
00386 "Byte Mode",
00387 "Parallel Port FIFO Mode",
00388 "ECP FIFO Mode",
00389 "EPP Mode",
00390 "Reserved",
00391 "FIFO Test Mode",
00392 "Configuration Mode"
00393 };
00394
00395 int ret;
00396
00397 FUNC_ENTER();
00398
00399 ret=1;
00400
00401 switch (preprprt(port))
00402 {
00403 case lptN_A:
00404 ret=0;
00405 break;
00406 case lptEPPc:
00407 DBG_PRINT((DBG_PREFIX ", EPP-Enable-Timeout-Bit-Detection-Control-Word:"
00408 " %s", EPPcontrol(port)));
00409 break;
00410
00411 case lptECP:
00412 DBG_PRINT((DBG_PREFIX ", ECP-Mode: %s", ecpM[ECPmode(port)]));
00413 }
00414 DBG_PRINT((DBG_PREFIX ""));
00415
00416 FUNC_LEAVE_INT(ret);
00417 }
00418
00419
00432 NTSTATUS
00433 ParPortSetModeNt4(PDEVICE_EXTENSION Pdx)
00434 {
00435 NTSTATUS ntStatus = STATUS_SUCCESS;
00436 enum lptMode lptmode = Pdx->HandleEcpEppMyself & 0xFF;
00437 enum ecpMode oldecpmode = ecpNOECR;
00438
00439 FUNC_ENTER();
00440
00441 if (lptmode == lptN_A)
00442 {
00443 DBG_PRINT((DBG_PREFIX "Trying to find out mode of 0x%04x", Pdx->ParPortPortAddress));
00444 lptmode = LPTmode(Pdx->ParPortPortAddress);
00445 prport(Pdx->ParPortPortAddress);
00446 }
00447
00448 if (lptmode == lptECP)
00449 {
00450 oldecpmode = ECPmode(Pdx->ParPortPortAddress);
00451
00452 DBG_PRINT((DBG_PREFIX "Setting ECP mode to BYTE mode"));
00453 SetECPmode(Pdx->ParPortPortAddress, ecpBYTE);
00454
00455 DBG_PRINT((DBG_PREFIX "Checking if mode has changed:"));
00456 prport(Pdx->ParPortPortAddress);
00457 }
00458
00459 if (lptmode > lptSPP)
00460 {
00461 DBG_PRINT((DBG_PREFIX "Writing the value 0xE4 to 0x%04x", Pdx->ParPortPortAddress+2));
00462 WRITE_PORT_UCHAR(Pdx->ParPortPortAddress+2,0xE4);
00463 }
00464
00465 Pdx->HandleEcpEppMyself = (lptmode & 0xFF) | ((oldecpmode & 0xFF) << 8);
00466
00467 FUNC_LEAVE_NTSTATUS(ntStatus);
00468 }
00469
00483 NTSTATUS
00484 ParPortUnsetModeNt4(PDEVICE_EXTENSION Pdx)
00485 {
00486 NTSTATUS ntStatus = STATUS_SUCCESS;
00487 enum lptMode lptmode = Pdx->HandleEcpEppMyself & 0xFF;
00488 enum ecpMode oldecpmode = (Pdx->HandleEcpEppMyself & 0xFF00) >> 8;
00489
00490 FUNC_ENTER();
00491
00492 if (lptmode == lptECP)
00493 {
00494 DBG_PRINT((DBG_PREFIX "Setting ECP mode back to standard mode"));
00495 SetECPmode(Pdx->ParPortPortAddress, oldecpmode);
00496
00497 DBG_PRINT((DBG_PREFIX "Checking if mode has changed:"));
00498 prport(Pdx->ParPortPortAddress);
00499 }
00500
00501 FUNC_LEAVE_NTSTATUS(ntStatus);
00502 }
00503
00516 extern VOID
00517 cbmiec_udelay(IN ULONG howlong);
00518
00519 NTSTATUS
00520 ParPortSetMode(PDEVICE_EXTENSION Pdx)
00521 {
00522 NTSTATUS ntStatus = STATUS_LOGON_FAILURE;
00523
00524 FUNC_ENTER();
00525
00526 if (!Pdx->HandleEcpEppMyself)
00527 {
00528
00529
00530 ntStatus = ParPortSetModeWdm(Pdx);
00531 }
00532
00533 if (Pdx->HandleEcpEppMyself || ((ntStatus == STATUS_INVALID_PARAMETER) && Pdx->IsNT4))
00534 {
00535 ntStatus = ParPortSetModeNt4(Pdx);
00536 cbmiec_udelay(1000 * 10);
00537 }
00538
00539 FUNC_LEAVE_NTSTATUS(ntStatus);
00540 }
00541
00555 NTSTATUS
00556 ParPortUnsetMode(PDEVICE_EXTENSION Pdx)
00557 {
00558 NTSTATUS ntStatus;
00559
00560 FUNC_ENTER();
00561
00562 if (Pdx->HandleEcpEppMyself == 0)
00563 {
00564 ntStatus = ParPortUnsetModeWdm(Pdx);
00565 }
00566 else
00567 {
00568 ntStatus = ParPortUnsetModeNt4(Pdx);
00569 }
00570
00571 FUNC_LEAVE_NTSTATUS(ntStatus);
00572 }