ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

hardware.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.