⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 initunlo.c

📁 串口Windows驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
   oldIERContents = READ_INTERRUPT_ENABLE(Extension->Controller);

   //
   // Go up to power level for a very short time to prevent
   // any interrupts from this device from coming in.
   //

   KeRaiseIrql(
              POWER_LEVEL,
              &oldIrql
              );

   WRITE_INTERRUPT_ENABLE(
                         Extension->Controller,
                         0x0f
                         );

   value1 = READ_INTERRUPT_ENABLE(Extension->Controller);
   value1 = value1 << 8;
   value1 |= READ_RECEIVE_BUFFER(Extension->Controller);

   READ_DIVISOR_LATCH(
                     Extension->Controller,
                     &value2
                     );

   WRITE_LINE_CONTROL(
                     Extension->Controller,
                     oldLCRContents
                     );

   //
   // Put the ier back to where it was before.  If we are on a
   // level sensitive port this should prevent the interrupts
   // from coming in.  If we are on a latched, we don't care
   // cause the interrupts generated will just get dropped.
   //

   WRITE_INTERRUPT_ENABLE(
                         Extension->Controller,
                         oldIERContents
                         );

   KeLowerIrql(oldIrql);

   if (value1 == value2) {

      SerialLogError(
                    Extension->DeviceObject->DriverObject,
                    Extension->DeviceObject,
                    Extension->OriginalController,
                    SerialPhysicalZero,
                    0,
                    0,
                    0,
                    62,
                    STATUS_SUCCESS,
                    SERIAL_DLAB_INVALID,
                    InsertString->Length+sizeof(WCHAR),
                    InsertString->Buffer,
                    0,
                    NULL
                    );
      returnValue = FALSE;
      goto AllDone;

   }

   AllDone: ;


   //
   // If we think that there is a serial device then we determine
   // if a fifo is present.
   //

   if (returnValue) {

      //
      // Well, we think it's a serial device.  Absolutely
      // positively, prevent interrupts from occuring.
      //
      // We disable all the interrupt enable bits, and
      // push down all the lines in the modem control
      // We only needed to push down OUT2 which in
      // PC's must also be enabled to get an interrupt.
      //

      DISABLE_ALL_INTERRUPTS(Extension->Controller);

      WRITE_MODEM_CONTROL(Extension->Controller, (UCHAR)0);

      //
      // See if this is a 16550.  We do this by writing to
      // what would be the fifo control register with a bit
      // pattern that tells the device to enable fifo's.
      // We then read the iterrupt Id register to see if the
      // bit pattern is present that identifies the 16550.
      //

      WRITE_FIFO_CONTROL(
                        Extension->Controller,
                        SERIAL_FCR_ENABLE
                        );

      regContents = READ_INTERRUPT_ID_REG(Extension->Controller);

      if (regContents & SERIAL_IIR_FIFOS_ENABLED) {

         //
         // Save off that the device supports fifos.
         //

         Extension->FifoPresent = TRUE;

         //
         // There is a fine new "super" IO chip out there that
         // will get stuck with a line status interrupt if you
         // attempt to clear the fifo and enable it at the same
         // time if data is present.  The best workaround seems
         // to be that you should turn off the fifo read a single
         // byte, and then re-enable the fifo.
         //

         WRITE_FIFO_CONTROL(
                           Extension->Controller,
                           (UCHAR)0
                           );

         READ_RECEIVE_BUFFER(Extension->Controller);

         //
         // There are fifos on this card.  Set the value of the
         // receive fifo to interrupt when 4 characters are present.
         //

         WRITE_FIFO_CONTROL(Extension->Controller,
                            (UCHAR)(SERIAL_FCR_ENABLE
                                    | Extension->RxFifoTrigger
                                    | SERIAL_FCR_RCVR_RESET
                                    | SERIAL_FCR_TXMT_RESET));

      }

      //
      // The !Extension->FifoPresent is included in the test so that
      // broken chips like the WinBond will still work after we test
      // for the fifo.
      //

      if (!ForceFifo || !Extension->FifoPresent) {

         Extension->FifoPresent = FALSE;
         WRITE_FIFO_CONTROL(
                           Extension->Controller,
                           (UCHAR)0
                           );

      }

      if (Extension->FifoPresent) {

         if (LogFifo) {

            SerialLogError(
                          Extension->DeviceObject->DriverObject,
                          Extension->DeviceObject,
                          Extension->OriginalController,
                          SerialPhysicalZero,
                          0,
                          0,
                          0,
                          15,
                          STATUS_SUCCESS,
                          SERIAL_FIFO_PRESENT,
                          InsertString->Length+sizeof(WCHAR),
                          InsertString->Buffer,
                          0,
                          NULL
                          );

         }

         SerialDbgPrintEx(SERDIAG1, "Fifo's detected at port address: %x\n",
                          Extension->Controller);

      }

      //
      // In case we are dealing with a bitmasked multiportcard,
      // that has the mask register enabled, enable the
      // interrupts.
      //

      if (Extension->InterruptStatus) {
         if (Extension->Indexed) {
            WRITE_PORT_UCHAR(Extension->InterruptStatus, (UCHAR)0xFF);
         } else {
            //
            // Either we are standalone or already mapped
            //

            if (Extension->OurIsrContext == Extension) {
               //
               // This is a standalone
               //

               WRITE_PORT_UCHAR(Extension->InterruptStatus,
                                (UCHAR)(1 << (Extension->PortIndex - 1)));
            } else {
               //
               // One of many
               //

               WRITE_PORT_UCHAR(Extension->InterruptStatus,
                                (UCHAR)((PSERIAL_MULTIPORT_DISPATCH)Extension->
                                        OurIsrContext)->UsablePortMask);
            }
         }
      }

   }

   return returnValue;

}


BOOLEAN
SerialReset(
           IN PVOID Context
           )

/*++

Routine Description:

    This places the hardware in a standard configuration.

    NOTE: This assumes that it is called at interrupt level.


Arguments:

    Context - The device extension for serial device
    being managed.

Return Value:

    Always FALSE.

--*/

{

   PSERIAL_DEVICE_EXTENSION extension = Context;
   UCHAR regContents;
   UCHAR oldModemControl;
   ULONG i;
   SERIAL_LOCKED_PAGED_CODE();

   //
   // Adjust the out2 bit.
   // This will also prevent any interrupts from occuring.
   //

   oldModemControl = READ_MODEM_CONTROL(extension->Controller);

   WRITE_MODEM_CONTROL(extension->Controller,
                       (UCHAR)(oldModemControl & ~SERIAL_MCR_OUT2));


   //
   // Reset the fifo's if there are any.
   //

   if (extension->FifoPresent) {


      //
      // There is a fine new "super" IO chip out there that
      // will get stuck with a line status interrupt if you
      // attempt to clear the fifo and enable it at the same
      // time if data is present.  The best workaround seems
      // to be that you should turn off the fifo read a single
      // byte, and then re-enable the fifo.
      //

      WRITE_FIFO_CONTROL(
                        extension->Controller,
                        (UCHAR)0
                        );

      READ_RECEIVE_BUFFER(extension->Controller);

      WRITE_FIFO_CONTROL(
                        extension->Controller,
                        (UCHAR)(SERIAL_FCR_ENABLE | extension->RxFifoTrigger |
                                SERIAL_FCR_RCVR_RESET | SERIAL_FCR_TXMT_RESET)
                        );

   }

   //
   // Make sure that the line control set up correct.
   //
   // 1) Make sure that the Divisor latch select is set
   //    up to select the transmit and receive register.
   //
   // 2) Make sure that we aren't in a break state.
   //

   regContents = READ_LINE_CONTROL(extension->Controller);
   regContents &= ~(SERIAL_LCR_DLAB | SERIAL_LCR_BREAK);

   WRITE_LINE_CONTROL(
                     extension->Controller,
                     regContents
                     );

   //
   // Read the receive buffer until the line status is
   // clear.  (Actually give up after a 5 reads.)
   //

   for (i = 0;
       i < 5;
       i++
       ) {

      if (IsNotNEC_98) {
         READ_RECEIVE_BUFFER(extension->Controller);
         if (!(READ_LINE_STATUS(extension->Controller) & 1)) {

            break;

         }
      } else {
          //
          // I get incorrect data when read enpty buffer.
          // But do not read no data! for PC98!
          //
          if (!(READ_LINE_STATUS(extension->Controller) & 1)) {

             break;

          }
          READ_RECEIVE_BUFFER(extension->Controller);
      }

   }

   //
   // Read the modem status until the low 4 bits are
   // clear.  (Actually give up after a 5 reads.)
   //

   for (i = 0;
       i < 1000;
       i++
       ) {

      if (!(READ_MODEM_STATUS(extension->Controller) & 0x0f)) {

         break;

      }

   }

   //
   // Now we set the line control, modem control, and the
   // baud to what they should be.
   //

   //
   // See if we have to enable special Auto Flow Control
   //

   if (extension->TL16C550CAFC) {
      oldModemControl = READ_MODEM_CONTROL(extension->Controller);

      WRITE_MODEM_CONTROL(extension->Controller,
                          (UCHAR)(oldModemControl | SERIAL_MCR_TL16C550CAFE));
   }



   SerialSetLineControl(extension);

   SerialSetupNewHandFlow(
                         extension,
                         &extension->HandFlow
                         );

   SerialHandleModemUpdate(
                          extension,
                          FALSE
                          );

   {
      SHORT  appropriateDivisor;
      SERIAL_IOCTL_SYNC s;

      SerialGetDivisorFromBaud(
                              extension->ClockRate,
                              extension->CurrentBaud,
                              &appropriateDivisor
                              );
      s.Extension = extension;
      s.Data = (PVOID)appropriateDivisor;
      SerialSetBaud(&s);
   }

   //
   // Enable which interrupts we want to receive.
   //
   // NOTE NOTE: This does not actually let interrupts
   // occur.  We must still raise the OUT2 bit in the
   // modem control register.  We will do that on open.
   //

   ENABLE_ALL_INTERRUPTS(extension->Controller);

   //
   // Read the interrupt id register until the low bit is
   // set.  (Actually give up after a 5 reads.)
   //

   for (i = 0;
       i < 5;
       i++
       ) {

      if (READ_INTERRUPT_ID_REG(extension->Controller) & 0x01) {

         break;

      }

   }

   //
   // Now we know that nothing could be transmitting at this point
   // so we set the HoldingEmpty indicator.
   //

   extension->HoldingEmpty = TRUE;

   return FALSE;
}


NTSTATUS
SerialGetDivisorFromBaud(
                        IN ULONG ClockRate,
                        IN LONG DesiredBaud,
                        OUT PSHORT AppropriateDivisor
                        )

/*++

Routine Description:

    This routine will determine a divisor based on an unvalidated
    baud rate.

Arguments:

    ClockRate - The clock input to the controller.

    DesiredBaud - The baud rate for whose divisor we seek.

    AppropriateDivisor - Given that the DesiredBaud is valid, the
    LONG pointed to by this parameter will be set to the appropriate
    value.  NOTE: The long is undefined if the DesiredBaud is not
    supported.

Return Value:

    This fun

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -