Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenhardware.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS ISA PnP Bus driver 00003 * FILE: hardware.c 00004 * PURPOSE: Hardware support code 00005 * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org) 00006 */ 00007 #include <isapnp.h> 00008 #include <isapnphw.h> 00009 00010 #define NDEBUG 00011 #include <debug.h> 00012 00013 static 00014 inline 00015 VOID 00016 WriteAddress(USHORT Address) 00017 { 00018 WRITE_PORT_UCHAR((PUCHAR)ISAPNP_ADDRESS, Address); 00019 } 00020 00021 static 00022 inline 00023 VOID 00024 WriteData(USHORT Data) 00025 { 00026 WRITE_PORT_UCHAR((PUCHAR)ISAPNP_WRITE_DATA, Data); 00027 } 00028 00029 static 00030 inline 00031 UCHAR 00032 ReadData(PUCHAR ReadDataPort) 00033 { 00034 return READ_PORT_UCHAR(ReadDataPort); 00035 } 00036 00037 static 00038 inline 00039 VOID 00040 WriteByte(USHORT Address, USHORT Value) 00041 { 00042 WriteAddress(Address); 00043 WriteData(Value); 00044 } 00045 00046 static 00047 inline 00048 UCHAR 00049 ReadByte(PUCHAR ReadDataPort, USHORT Address) 00050 { 00051 WriteAddress(Address); 00052 return ReadData(ReadDataPort); 00053 } 00054 00055 static 00056 inline 00057 USHORT 00058 ReadWord(PUCHAR ReadDataPort, USHORT Address) 00059 { 00060 return ((ReadByte(ReadDataPort, Address) << 8) | 00061 (ReadByte(ReadDataPort, Address + 1))); 00062 } 00063 00064 static 00065 inline 00066 VOID 00067 SetReadDataPort(PUCHAR ReadDataPort) 00068 { 00069 WriteByte(ISAPNP_READPORT, ((ULONG_PTR)ReadDataPort >> 2)); 00070 } 00071 00072 static 00073 inline 00074 VOID 00075 EnterIsolationState(VOID) 00076 { 00077 WriteAddress(ISAPNP_SERIALISOLATION); 00078 } 00079 00080 static 00081 inline 00082 VOID 00083 WaitForKey(VOID) 00084 { 00085 WriteByte(ISAPNP_CONFIGCONTROL, ISAPNP_CONFIG_WAIT_FOR_KEY); 00086 } 00087 00088 static 00089 inline 00090 VOID 00091 ResetCsn(VOID) 00092 { 00093 WriteByte(ISAPNP_CONFIGCONTROL, ISAPNP_CONFIG_RESET_CSN); 00094 } 00095 00096 static 00097 inline 00098 VOID 00099 Wake(USHORT Csn) 00100 { 00101 WriteByte(ISAPNP_WAKE, Csn); 00102 } 00103 00104 static 00105 inline 00106 USHORT 00107 ReadResourceData(PUCHAR ReadDataPort) 00108 { 00109 return ReadByte(ReadDataPort, ISAPNP_RESOURCEDATA); 00110 } 00111 00112 static 00113 inline 00114 USHORT 00115 ReadStatus(PUCHAR ReadDataPort) 00116 { 00117 return ReadByte(ReadDataPort, ISAPNP_STATUS); 00118 } 00119 00120 static 00121 inline 00122 VOID 00123 WriteCsn(USHORT Csn) 00124 { 00125 WriteByte(ISAPNP_CARDSELECTNUMBER, Csn); 00126 } 00127 00128 static 00129 inline 00130 VOID 00131 WriteLogicalDeviceNumber(USHORT LogDev) 00132 { 00133 WriteByte(ISAPNP_LOGICALDEVICENUMBER, LogDev); 00134 } 00135 00136 static 00137 inline 00138 VOID 00139 ActivateDevice(USHORT LogDev) 00140 { 00141 WriteLogicalDeviceNumber(LogDev); 00142 WriteByte(ISAPNP_ACTIVATE, 1); 00143 } 00144 00145 static 00146 inline 00147 VOID 00148 DeactivateDevice(USHORT LogDev) 00149 { 00150 WriteLogicalDeviceNumber(LogDev); 00151 WriteByte(ISAPNP_ACTIVATE, 0); 00152 } 00153 00154 static 00155 inline 00156 USHORT 00157 ReadIoBase(PUCHAR ReadDataPort, USHORT Index) 00158 { 00159 return ReadWord(ReadDataPort, ISAPNP_IOBASE(Index)); 00160 } 00161 00162 static 00163 inline 00164 USHORT 00165 ReadIrqNo(PUCHAR ReadDataPort, USHORT Index) 00166 { 00167 return ReadByte(ReadDataPort, ISAPNP_IRQNO(Index)); 00168 } 00169 00170 static 00171 inline 00172 VOID 00173 HwDelay(VOID) 00174 { 00175 KeStallExecutionProcessor(1000); 00176 } 00177 00178 static 00179 inline 00180 USHORT 00181 NextLFSR(USHORT Lfsr, USHORT InputBit) 00182 { 00183 ULONG NextLfsr = Lfsr >> 1; 00184 00185 NextLfsr |= (((Lfsr ^ NextLfsr) ^ InputBit)) << 7; 00186 00187 return NextLfsr; 00188 } 00189 00190 static 00191 VOID 00192 SendKey(VOID) 00193 { 00194 USHORT i, Lfsr; 00195 00196 HwDelay(); 00197 WriteAddress(0x00); 00198 WriteAddress(0x00); 00199 00200 Lfsr = ISAPNP_LFSR_SEED; 00201 for (i = 0; i < 32; i++) 00202 { 00203 WriteAddress(Lfsr); 00204 Lfsr = NextLFSR(Lfsr, 0); 00205 } 00206 } 00207 00208 static 00209 USHORT 00210 PeekByte(PUCHAR ReadDataPort) 00211 { 00212 USHORT i; 00213 00214 for (i = 0; i < 20; i++) 00215 { 00216 if (ReadStatus(ReadDataPort) & 0x01) 00217 return ReadResourceData(ReadDataPort); 00218 00219 HwDelay(); 00220 } 00221 00222 return 0xFF; 00223 } 00224 00225 static 00226 VOID 00227 Peek(PUCHAR ReadDataPort, PVOID Buffer, ULONG Length) 00228 { 00229 USHORT i, byte; 00230 00231 for (i = 0; i < Length; i++) 00232 { 00233 byte = PeekByte(ReadDataPort); 00234 if (Buffer) 00235 *((PUCHAR)Buffer + i) = byte; 00236 } 00237 } 00238 00239 static 00240 USHORT 00241 IsaPnpChecksum(PISAPNP_IDENTIFIER Identifier) 00242 { 00243 USHORT i,j, Lfsr, Byte; 00244 00245 Lfsr = ISAPNP_LFSR_SEED; 00246 for (i = 0; i < 8; i++) 00247 { 00248 Byte = *(((PUCHAR)Identifier) + i); 00249 for (j = 0; j < 8; j++) 00250 { 00251 Lfsr = NextLFSR(Lfsr, Byte); 00252 Byte >>= 1; 00253 } 00254 } 00255 00256 return Lfsr; 00257 } 00258 00259 static 00260 BOOLEAN 00261 FindTag(PUCHAR ReadDataPort, USHORT WantedTag, PVOID Buffer, ULONG Length) 00262 { 00263 USHORT Tag, TagLen; 00264 00265 do 00266 { 00267 Tag = PeekByte(ReadDataPort); 00268 if (ISAPNP_IS_SMALL_TAG(Tag)) 00269 { 00270 TagLen = ISAPNP_SMALL_TAG_LEN(Tag); 00271 Tag = ISAPNP_SMALL_TAG_NAME(Tag); 00272 } 00273 else 00274 { 00275 TagLen = PeekByte(ReadDataPort) + (PeekByte(ReadDataPort) << 8); 00276 Tag = ISAPNP_LARGE_TAG_NAME(Tag); 00277 } 00278 00279 if (Tag == WantedTag) 00280 { 00281 if (Length > TagLen) 00282 Length = TagLen; 00283 00284 Peek(ReadDataPort, Buffer, Length); 00285 00286 return TRUE; 00287 } 00288 else 00289 { 00290 Peek(ReadDataPort, NULL, Length); 00291 } 00292 } while (Tag != ISAPNP_TAG_END); 00293 00294 return FALSE; 00295 } 00296 00297 static 00298 BOOLEAN 00299 FindLogDevId(PUCHAR ReadDataPort, USHORT LogDev, PISAPNP_LOGDEVID LogDeviceId) 00300 { 00301 USHORT i; 00302 00303 for (i = 0; i <= LogDev; i++) 00304 { 00305 if (!FindTag(ReadDataPort, ISAPNP_TAG_LOGDEVID, LogDeviceId, sizeof(*LogDeviceId))) 00306 return FALSE; 00307 } 00308 00309 return TRUE; 00310 } 00311 00312 static 00313 INT 00314 TryIsolate(PUCHAR ReadDataPort) 00315 { 00316 ISAPNP_IDENTIFIER Identifier; 00317 USHORT i, j; 00318 BOOLEAN Seen55aa, SeenLife; 00319 INT Csn = 0; 00320 USHORT Byte, Data; 00321 00322 DPRINT("Setting read data port: 0x%x\n", ReadDataPort); 00323 00324 WaitForKey(); 00325 SendKey(); 00326 00327 ResetCsn(); 00328 HwDelay(); 00329 HwDelay(); 00330 00331 WaitForKey(); 00332 SendKey(); 00333 Wake(0x00); 00334 00335 SetReadDataPort(ReadDataPort); 00336 HwDelay(); 00337 00338 while (TRUE) 00339 { 00340 EnterIsolationState(); 00341 HwDelay(); 00342 00343 RtlZeroMemory(&Identifier, sizeof(Identifier)); 00344 00345 Seen55aa = SeenLife = FALSE; 00346 for (i = 0; i < 9; i++) 00347 { 00348 Byte = 0; 00349 for (j = 0; j < 8; j++) 00350 { 00351 Data = ReadData(ReadDataPort); 00352 HwDelay(); 00353 Data = ((Data << 8) | ReadData(ReadDataPort)); 00354 HwDelay(); 00355 Byte >>= 1; 00356 00357 if (Data != 0xFFFF) 00358 { 00359 SeenLife = TRUE; 00360 if (Data == 0x55AA) 00361 { 00362 Byte |= 0x80; 00363 Seen55aa = TRUE; 00364 } 00365 } 00366 } 00367 *(((PUCHAR)&Identifier) + i) = Byte; 00368 } 00369 00370 if (!Seen55aa) 00371 { 00372 if (Csn) 00373 { 00374 DPRINT("Found no more cards\n"); 00375 } 00376 else 00377 { 00378 if (SeenLife) 00379 { 00380 DPRINT("Saw life but no cards, trying new read port\n"); 00381 Csn = -1; 00382 } 00383 else 00384 { 00385 DPRINT("Saw no sign of life, abandoning isolation\n"); 00386 } 00387 } 00388 break; 00389 } 00390 00391 if (Identifier.Checksum != IsaPnpChecksum(&Identifier)) 00392 { 00393 DPRINT("Bad checksum, trying next read data port\n"); 00394 Csn = -1; 00395 break; 00396 } 00397 00398 Csn++; 00399 00400 WriteCsn(Csn); 00401 HwDelay(); 00402 00403 Wake(0x00); 00404 HwDelay(); 00405 } 00406 00407 WaitForKey(); 00408 00409 if (Csn > 0) 00410 { 00411 DPRINT("Found %d cards at read port 0x%x\n", Csn, ReadDataPort); 00412 } 00413 00414 return Csn; 00415 } 00416 00417 static 00418 PUCHAR 00419 Isolate(VOID) 00420 { 00421 PUCHAR ReadPort; 00422 00423 for (ReadPort = (PUCHAR)ISAPNP_READ_PORT_START; 00424 (ULONG_PTR)ReadPort <= ISAPNP_READ_PORT_MAX; 00425 ReadPort += ISAPNP_READ_PORT_STEP) 00426 { 00427 /* Avoid the NE2000 probe space */ 00428 if ((ULONG_PTR)ReadPort >= 0x280 && 00429 (ULONG_PTR)ReadPort <= 0x380) 00430 continue; 00431 00432 if (TryIsolate(ReadPort) > 0) 00433 return ReadPort; 00434 } 00435 00436 return 0; 00437 } 00438 00439 VOID 00440 DeviceActivation(PISAPNP_LOGICAL_DEVICE IsaDevice, 00441 BOOLEAN Activate) 00442 { 00443 WaitForKey(); 00444 SendKey(); 00445 Wake(IsaDevice->CSN); 00446 00447 if (Activate) 00448 ActivateDevice(IsaDevice->LDN); 00449 else 00450 DeactivateDevice(IsaDevice->LDN); 00451 00452 HwDelay(); 00453 00454 WaitForKey(); 00455 } 00456 00457 NTSTATUS 00458 ProbeIsaPnpBus(PISAPNP_FDO_EXTENSION FdoExt) 00459 { 00460 PISAPNP_LOGICAL_DEVICE LogDevice; 00461 ISAPNP_IDENTIFIER Identifier; 00462 ISAPNP_LOGDEVID LogDevId; 00463 USHORT Csn; 00464 USHORT LogDev; 00465 PDEVICE_OBJECT Pdo; 00466 NTSTATUS Status; 00467 00468 ASSERT(FdoExt->ReadDataPort); 00469 00470 for (Csn = 1; Csn <= 0xFF; Csn++) 00471 { 00472 for (LogDev = 0; LogDev <= 0xFF; LogDev++) 00473 { 00474 Status = IoCreateDevice(FdoExt->Common.Self->DriverObject, 00475 sizeof(ISAPNP_LOGICAL_DEVICE), 00476 NULL, 00477 FILE_DEVICE_CONTROLLER, 00478 FILE_DEVICE_SECURE_OPEN, 00479 FALSE, 00480 &Pdo); 00481 if (!NT_SUCCESS(Status)) 00482 return Status; 00483 00484 Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; 00485 00486 LogDevice = Pdo->DeviceExtension; 00487 00488 RtlZeroMemory(LogDevice, sizeof(ISAPNP_LOGICAL_DEVICE)); 00489 00490 LogDevice->Common.Self = Pdo; 00491 LogDevice->Common.IsFdo = FALSE; 00492 LogDevice->Common.State = dsStopped; 00493 00494 LogDevice->CSN = Csn; 00495 LogDevice->LDN = LogDev; 00496 00497 WaitForKey(); 00498 SendKey(); 00499 Wake(Csn); 00500 00501 Peek(FdoExt->ReadDataPort, &Identifier, sizeof(Identifier)); 00502 00503 if (Identifier.VendorId & 0x80) 00504 { 00505 IoDeleteDevice(LogDevice->Common.Self); 00506 return STATUS_SUCCESS; 00507 } 00508 00509 if (!FindLogDevId(FdoExt->ReadDataPort, LogDev, &LogDevId)) 00510 break; 00511 00512 WriteLogicalDeviceNumber(LogDev); 00513 00514 LogDevice->VendorId = LogDevId.VendorId; 00515 LogDevice->ProdId = LogDevId.ProdId; 00516 LogDevice->IoAddr = ReadIoBase(FdoExt->ReadDataPort, 0); 00517 LogDevice->IrqNo = ReadIrqNo(FdoExt->ReadDataPort, 0); 00518 00519 DPRINT1("Detected ISA PnP device - VID: 0x%x PID: 0x%x IoBase: 0x%x IRQ:0x%x\n", 00520 LogDevice->VendorId, LogDevice->ProdId, LogDevice->IoAddr, LogDevice->IrqNo); 00521 00522 WaitForKey(); 00523 00524 Pdo->Flags &= ~DO_DEVICE_INITIALIZING; 00525 00526 InsertTailList(&FdoExt->DeviceListHead, &LogDevice->ListEntry); 00527 FdoExt->DeviceCount++; 00528 } 00529 } 00530 00531 return STATUS_SUCCESS; 00532 } 00533 00534 NTSTATUS 00535 NTAPI 00536 IsaHwDetectReadDataPort( 00537 IN PISAPNP_FDO_EXTENSION FdoExt) 00538 { 00539 FdoExt->ReadDataPort = Isolate(); 00540 if (!FdoExt->ReadDataPort) 00541 { 00542 DPRINT1("No read data port found\n"); 00543 return STATUS_UNSUCCESSFUL; 00544 } 00545 00546 DPRINT1("Detected read data port at 0x%x\n", FdoExt->ReadDataPort); 00547 00548 return STATUS_SUCCESS; 00549 } 00550 00551 NTSTATUS 00552 NTAPI 00553 IsaHwActivateDevice( 00554 IN PISAPNP_LOGICAL_DEVICE LogicalDevice) 00555 { 00556 DeviceActivation(LogicalDevice, 00557 TRUE); 00558 00559 return STATUS_SUCCESS; 00560 } 00561 00562 NTSTATUS 00563 NTAPI 00564 IsaHwDeactivateDevice( 00565 IN PISAPNP_LOGICAL_DEVICE LogicalDevice) 00566 { 00567 DeviceActivation(LogicalDevice, 00568 FALSE); 00569 00570 return STATUS_SUCCESS; 00571 } 00572 00573 NTSTATUS 00574 NTAPI 00575 IsaHwFillDeviceList( 00576 IN PISAPNP_FDO_EXTENSION FdoExt) 00577 { 00578 return ProbeIsaPnpBus(FdoExt); 00579 } Generated on Sat May 26 2012 04:17:52 for ReactOS by
1.7.6.1
|