Beispiel #1
0
VOID
ScsiPortReadRegisterBufferUchar(
    IN PUCHAR Register,
    IN PUCHAR Buffer,
    IN ULONG  Count
)

/*++

Routine Description:

    Read a buffer of unsigned bytes from the specified register address.

Arguments:

    Register - Supplies a pointer to the port address.
    Buffer - Supplies a pointer to the data buffer area.
    Count - The count of items to move.

Return Value:

    None

--*/

{

    READ_REGISTER_BUFFER_UCHAR(Register, Buffer, Count);

}
Beispiel #2
0
VOID
NTAPI
ScsiPortReadRegisterBufferUchar(
    IN PUCHAR Register,
    IN PUCHAR Buffer,
    IN ULONG Count)
{
    READ_REGISTER_BUFFER_UCHAR(Register, Buffer, Count);
}
Beispiel #3
0
VOID
NTAPI
VideoPortReadRegisterBufferUchar(
    PUCHAR Register,
    PUCHAR Buffer,
    ULONG Count)
{
    READ_REGISTER_BUFFER_UCHAR(Register, Buffer, Count);
}
Beispiel #4
0
ULONG
EISAReadRegisterBufferUCHAR (
    IN ULONG BusNumber,
    IN ULONG Offset,
    OUT PVOID Buffer,
    IN ULONG Length
)
/*++

Routine Description:

    This reads EISA memory space using byte reads.

Arguments:

    BusNumber		EISA bus number, starting with 0.

    Offset		Byte offset from the beginning of EISA space for
    			this bus.

			This must be based off the .IoStart value in the
			EISA adapter's ConfigurationData, which is held in
			the Component Data Structure node.  Therefore, this
			will already have the EISA QVA bits set up.

    Buffer		A pointer to the data area to receive the EISA data.

    Length		Number of bytes to read.


Return Value:

    This returns the number of bytes actually read.  If this is not
    equal to the Length argument, an error has occurred.  Explicitly
    detected errors are signalled by returning a value of 0.

--*/

{
    //
    // Check for illegal values for Jensen.
    //

    if (BusNumber != 0) {
        return (0);
    }

    //
    // Call HAL library function with QVA bit or'd in.
    //

    READ_REGISTER_BUFFER_UCHAR((PUCHAR)Offset, Buffer, Length);

    return (Length);
}
Beispiel #5
0
VOID
DrainTransmit( PDIGI_CONTROLLER_EXTENSION ControllerExt,
               PDIGI_DEVICE_EXTENSION DeviceExt,
               PIRP Irp )
/*++

Routine Description:

   We do the necessary checks to determine if the controller has
   transmitted all the data it has been given.

   The check basically is:

      if( CIN == COUT
          TIN == TOUT
          TBusy == 0 )
          transmit buffer is empty.


   NOTE: Care should be taken when using this function, and at
         what dispatch level it is being called from.  I don't do any
         synch'ing with the WriteQueue in the DeviceObject.  So it is
         potentially possible that data could keep getting put on the
         controller while the function is waiting for it to drain.

Arguments:

   ControllerExt - a pointer to this devices controllers extension.

   DeviceObject - a pointer to this devices object.

   Irp - Pointer to the current Irp request whose context this function
         is being called.  This allows us to determine if the Irp
         has been cancelled.

Return Value:


--*/
{
   PFEP_CHANNEL_STRUCTURE ChInfo;
   PCOMMAND_STRUCT CommandQ;
   COMMAND_STRUCT CmdStruct;
   UCHAR TBusy;
   ULONG count;

   USHORT OrgTout, Tin, Tout;

   TIME DelayInterval;


   ChInfo = (PFEP_CHANNEL_STRUCTURE)(ControllerExt->VirtualAddress +
                                     DeviceExt->ChannelInfo.Offset);

   EnableWindow( ControllerExt, DeviceExt->ChannelInfo.Window );
   Tin = READ_REGISTER_USHORT( &ChInfo->tin );
   Tout = READ_REGISTER_USHORT( &ChInfo->tout );
   TBusy = READ_REGISTER_UCHAR( &ChInfo->tbusy );
   DisableWindow( ControllerExt );

   OrgTout = Tout;

   //
   // Get the command queue info
   //
   CommandQ = ((PCOMMAND_STRUCT)(ControllerExt->VirtualAddress + FEP_CIN));

   EnableWindow( ControllerExt, ControllerExt->Global.Window );
   READ_REGISTER_BUFFER_UCHAR( (PUCHAR)CommandQ,
                               (PUCHAR)&CmdStruct,
                               sizeof(CmdStruct) );
   DisableWindow( ControllerExt );

   //
   // Delay for 10 milliseconds
   //
#if rmm < 807
   DelayInterval = RtlConvertLongToLargeInteger( -10 * 10000 );
#else
   DelayInterval.QuadPart = -10 * 10000;
#endif

   count = 0;

   while( ((Tin != Tout) ||
          (TBusy) ||
          (CmdStruct.cmHead != CmdStruct.cmTail)) &&
          !Irp->Cancel )
   {
      ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL ); // not DPC, or KeDelay won't ever return
      KeDelayExecutionThread( KernelMode,
                              FALSE,
                              &DelayInterval );

      EnableWindow( ControllerExt, DeviceExt->ChannelInfo.Window );
      Tin = READ_REGISTER_USHORT( &ChInfo->tin );
      Tout = READ_REGISTER_USHORT( &ChInfo->tout );
      TBusy = READ_REGISTER_UCHAR( &ChInfo->tbusy );
      DisableWindow( ControllerExt );

      EnableWindow( ControllerExt, ControllerExt->Global.Window );
      READ_REGISTER_BUFFER_UCHAR( (PUCHAR)CommandQ,
                                  (PUCHAR)&CmdStruct,
                                  sizeof(CmdStruct) );
      DisableWindow( ControllerExt );

      if( Tout != OrgTout )
      {
         count = 0;
         OrgTout = Tout;
      }

      if( count++ > 2500 )
      {
         //
         // We have waited for 25 seconds and haven't seen the transmit
         // buffer change.  Assume we are in a deadlock flow control state
         // and exit!
         //

         //
         // We go ahead and flush the transmit queue because a close
         // may be following soon, and we don't want it to have to
         // wait again.  Basically, it had its chance to drain.
         //
         FlushTransmitBuffer( ControllerExt, DeviceExt );

         break;
      }

   }

}  // end DrainTransmit
Beispiel #6
0
VOID
DigiServiceEvent( IN PDIGI_CONTROLLER_EXTENSION ControllerExt,
                  IN USHORT Ein,
                  IN USHORT Eout )

/*++

Routine Description:


Arguments:


Return Value:


--*/

{
   const USHORT Emax = 0x03FC;

   DigiDump( (DIGIFLOW|DIGIEVENT), ("Entering DigiServiceEvent\n") );

   // Event registers should be in range and DWORD-aligned.
   ASSERT( Ein <= Emax && (Ein & 3) == 0 );
   ASSERT( Eout <= Emax && (Eout & 3) == 0 );

   DigiDump( DIGIEVENT, ("---------  Ein(0x%.4x) != Eout(0x%.4x)\n",
                         Ein, Eout ) );

   for( ; Eout != Ein ; Eout += 4, Eout &= Emax )
   {
      PDIGI_DEVICE_EXTENSION DeviceExt;
      PFEP_EVENT pEvent;
      FEP_EVENT Event;
      ULONG EventReason;

      pEvent = (PFEP_EVENT)(ControllerExt->VirtualAddress +
                  ControllerExt->EventQueue.Offset + Eout );

      EnableWindow( ControllerExt, ControllerExt->EventQueue.Window );

      READ_REGISTER_BUFFER_UCHAR( (PUCHAR)pEvent, (PUCHAR)&Event, sizeof(Event) );

      DisableWindow( ControllerExt );

      if( (Event.Channel <= 0xDF) &&
          (Event.Channel < ControllerExt->NumberOfPorts) )
      {
         DeviceExt = ControllerExt->DeviceObjectArray[Event.Channel]->DeviceExtension;
      }
      else // bad command?
      {
         DeviceExt = NULL;
         DigiDump( DIGIEVENT, ("Event on unknown channel %d (flags = 0x%.2x), ignored\n", Event.Channel, Event.Flags) );
         continue;
      }

      DigiDump( DIGIEVENT, ("---------  Channel = %d\tFlags = 0x%.2x\n"
                            "---------  Current = 0x%.2x\tPrev. = 0x%.2x\n",
                           Event.Channel, Event.Flags, Event.CurrentModem,
                           Event.PreviousModem) );

      //
      // OK, let's process the event
      //

      if( Event.Flags & ~(FEP_ALL_EVENT_FLAGS) )
      {
         DigiDump( DIGIERRORS, ("Unknown event queue flag 0x%.2x\n",
               Event.Flags & ~(FEP_ALL_EVENT_FLAGS) ) );
         // Process the event bits that we *do* understand.
      }

      // Modem signals are always processed, regardless of whether the port is open.
      if( Event.Flags & FEP_MODEM_CHANGE_SIGNAL )
      {
         DigiDump( (DIGIMODEM|DIGIEVENT|DIGIWAIT),
                     ("---------  Modem Change Event (%s:%d)\n",
                      __FILE__, __LINE__ ) );

         KeAcquireSpinLockAtDpcLevel( &DeviceExt->ControlAccess );

         DigiDump( (DIGIMODEM|DIGIWAIT),
                             ("   CurrentModem = 0x%x\tPreviousModem = 0x%x\n",
                              Event.CurrentModem, Event.PreviousModem ));

         DeviceExt->CurrentModemSignals = Event.CurrentModem;

         KeReleaseSpinLockFromDpcLevel( &DeviceExt->ControlAccess );
      }

      // If the port isn't open, don't bother with the rest.
      if( DeviceExt->DeviceState != DIGI_DEVICE_STATE_OPEN )
      {
         // If we might return to OPEN, don't touch anything!
         if( DeviceExt->DeviceState != DIGI_DEVICE_STATE_CLEANUP)
         {
            if( Event.Flags & (FEP_RX_PRESENT | FEP_RECEIVE_BUFFER_OVERRUN | FEP_UART_RECEIVE_OVERRUN) )
            {
               PFEP_CHANNEL_STRUCTURE ChInfo;

               FlushReceiveBuffer( ControllerExt, DeviceExt );

               ChInfo = (PFEP_CHANNEL_STRUCTURE)(ControllerExt->VirtualAddress +
                                                DeviceExt->ChannelInfo.Offset);

               // Notify us when more data comes in.
               EnableWindow( ControllerExt, DeviceExt->ChannelInfo.Window );
               WRITE_REGISTER_UCHAR( &ChInfo->idata, TRUE );
               DisableWindow( ControllerExt );
            }
            // Don't flush transmit (might kill end of data).
         }
         continue;
      }

      // Reset event notifications.
      EventReason = 0;

      if( Event.Flags & FEP_EV_BREAK )
      {
         EventReason |= SERIAL_EV_BREAK;

         KeAcquireSpinLockAtDpcLevel( &DeviceExt->ControlAccess );
         DeviceExt->ErrorWord |= SERIAL_ERROR_BREAK;
         KeReleaseSpinLockFromDpcLevel( &DeviceExt->ControlAccess );
      }

      if( (Event.Flags & (FEP_TX_LOW | FEP_TX_EMPTY) ) )
      {
         PLIST_ENTRY WriteQueue;

#if DBG
         switch( Event.Flags & (FEP_TX_LOW | FEP_TX_EMPTY) )
         {
            case FEP_TX_LOW:
               DigiDump( (DIGIEVENT|DIGIWRITE), ("%s:\tTXLOW event\n", DeviceExt->DeviceDbgString) );
               break;
            case FEP_TX_EMPTY:
               DigiDump( (DIGIEVENT|DIGIWRITE), ("%s:\tTXEMPTY event\n", DeviceExt->DeviceDbgString) );
               break;
            default:
               DigiDump( (DIGIEVENT|DIGIWRITE), ("%s:\tTXLOW and TXEMPTY events\n", DeviceExt->DeviceDbgString) );
               break;
         }
#endif

         WriteQueue = &DeviceExt->WriteQueue;

         KeAcquireSpinLockAtDpcLevel( &DeviceExt->ControlAccess );

         if( !IsListEmpty( WriteQueue ) )
         {
            PIRP Irp;

            Irp = CONTAINING_RECORD( WriteQueue->Flink,
                                     IRP,
                                     Tail.Overlay.ListEntry );

            if( Irp->IoStatus.Information != MAXULONG )
            {
               PIO_STACK_LOCATION IrpSp;

               IrpSp = IoGetCurrentIrpStackLocation( Irp );

               if( IrpSp->MajorFunction == IRP_MJ_WRITE
               ||  (  IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL
                   && Irp->IoStatus.Information == 0
                   )
                 )
               {
                  DigiDump( DIGIEVENT, ("---------  WriteQueue list NOT empty\n") );

                  if( IrpSp->MajorFunction == IRP_MJ_WRITE )
                  {
                     ASSERT( Irp->IoStatus.Information < IrpSp->Parameters.Write.Length );
                  }
                  else
                  {
                     ASSERT(  IrpSp->Parameters.DeviceIoControl.IoControlCode ==
                                 IOCTL_SERIAL_IMMEDIATE_CHAR
                           || IrpSp->Parameters.DeviceIoControl.IoControlCode ==
                                 IOCTL_SERIAL_XOFF_COUNTER );
                  }

                  if( WriteTxBuffer( DeviceExt ) == STATUS_SUCCESS )
                  {
                     KIRQL OldIrql = DISPATCH_LEVEL;

                     DigiDump( DIGIEVENT, ("---------  Write complete.  Successfully completing Irp.\n"
                                           "---------  #bytes completing = %d\n",
                                           Irp->IoStatus.Information ) );

                     DIGI_INC_REFERENCE( Irp );
                     DigiTryToCompleteIrp( DeviceExt, &OldIrql,
                                           STATUS_SUCCESS, WriteQueue,
                                           NULL,
                                           &DeviceExt->WriteRequestTotalTimer,
                                           StartWriteRequest );

                     goto WriteDone; // skip unlock
                  } // WriteTxBuffer returned SUCCESS
               } // IRP is eligible for WriteTxBuffer
            } // IRP started
            KeReleaseSpinLockFromDpcLevel( &DeviceExt->ControlAccess );
WriteDone:;
         }
         else // empty(WQ)
         {
            DigiDump( DIGIEVENT, ("---------  WriteQueue was empty\n") );

            if( Event.Flags & FEP_TX_EMPTY )
               EventReason |= SERIAL_EV_TXEMPTY;

            KeReleaseSpinLockFromDpcLevel( &DeviceExt->ControlAccess );
         }
      } // FEP_TX_LOW | FEP_TX_EMPTY

      if( Event.Flags & FEP_RX_PRESENT )
      {
         PLIST_ENTRY ReadQueue;
         PFEP_CHANNEL_STRUCTURE ChInfo;
         USHORT Rin, Rout, Rmax, RxSize;

         DigiDump( DIGIEVENT, ("---------  Rcv Data Present Event: (%s:%d)\n",
                              __FILE__, __LINE__ ) );

GetReceivedData:;

         ChInfo = (PFEP_CHANNEL_STRUCTURE)(ControllerExt->VirtualAddress +
                                           DeviceExt->ChannelInfo.Offset);

         KeAcquireSpinLockAtDpcLevel( &DeviceExt->ControlAccess );

         EnableWindow( ControllerExt, DeviceExt->ChannelInfo.Window );
         Rout = READ_REGISTER_USHORT( &ChInfo->rout );
         Rin = READ_REGISTER_USHORT( &ChInfo->rin );
         Rmax = READ_REGISTER_USHORT( &ChInfo->rmax );
         DisableWindow( ControllerExt );

         if( (DeviceExt->WaitMask & SERIAL_EV_RXCHAR) &&
             (DeviceExt->PreviousRxChar != (ULONG)Rin) )
         {
            EventReason |= SERIAL_EV_RXCHAR;
         }

         if( (DeviceExt->WaitMask & SERIAL_EV_RXFLAG) &&
             (DeviceExt->UnscannedRXFLAGPosition != (ULONG)Rin) )
         {
            if( ScanReadBufferForSpecialCharacter( DeviceExt,
                                                   DeviceExt->SpecialChars.EventChar ) )
            {
               EventReason |= SERIAL_EV_RXFLAG;
            }
         }

         //
         // Determine if we are waiting to notify a 80% receive buffer
         // full.
         //
         //    NOTE: I assume the controller will continue to notify
         //          us that data is still in the buffer, even if
         //          we don't take the data out of the controller's
         //          buffer.
         //
         if( (DeviceExt->WaitMask & SERIAL_EV_RX80FULL)
         &&  !(DeviceExt->HistoryWait & SERIAL_EV_RX80FULL) ) // notification is already pending
         {
            //
            // Okay, is the receive buffer 80% or more full??
            //
            RxSize = (Rin - Rout) & Rmax;

            if( RxSize )
            {
               if( DeviceExt->SpecialFlags & DIGI_SPECIAL_FLAG_FAST_RAS )
               {
                  if( RxSize >= DeviceExt->ReceiveNotificationLimit )
                  {
                     EventReason |= SERIAL_EV_RX80FULL;
                  }
               }
               else // not RAS
               {
                  // Perform 32-bit math to avoid roundoff errors.
                  if( RxSize >= (USHORT) ( ((ULONG)Rmax + 1UL) * 8UL / 10UL) )
                  {
                     EventReason |= SERIAL_EV_RX80FULL;
                  }
                  else
                  {
                     USHORT RxHighWater;

                     EnableWindow( ControllerExt, DeviceExt->ChannelInfo.Window );
                     RxHighWater = READ_REGISTER_USHORT( &ChInfo->rhigh );
                     DisableWindow( ControllerExt );

                     // If flow control is engaged, trigger the event (we won't get any more data).
                     if( RxSize >= RxHighWater - 1 )
                     {
                        EventReason |= SERIAL_EV_RX80FULL;
                     }
                  }
               } // not RAS
            } // if data
         } // RX80FULL

         ReadQueue = &DeviceExt->ReadQueue;
         if( !IsListEmpty( ReadQueue ) )
         {
            PIRP Irp;

            Irp = CONTAINING_RECORD( ReadQueue->Flink,
                                     IRP,
                                     Tail.Overlay.ListEntry );

            if( DeviceExt->ReadStatus == STATUS_PENDING
            &&  Irp->IoStatus.Information != MAXULONG ) // not started yet
            {
               KIRQL OldIrql = DISPATCH_LEVEL;

               // Hold IRP across lock drop in ReadRxBuffer:ProcessSlowRead:DigiSatisfyWait.
               DIGI_INC_REFERENCE( Irp );

               if( STATUS_SUCCESS == ReadRxBuffer( DeviceExt, &OldIrql ) )
               {
#if DBG
                  if( DigiDebugLevel & DIGIRXTRACE )
                  {
                     PUCHAR Temp;
                     ULONG i;

                     Temp = Irp->AssociatedIrp.SystemBuffer;

                     DigiDump( DIGIRXTRACE, ("Read buffer contains: %s",
                                              DeviceExt->DeviceDbgString) );
                     for( i = 0;
                          i < Irp->IoStatus.Information;
                          i++ )
                     {
                        if( (i & 15) == 0 )
                           DigiDump( DIGIRXTRACE, ( "\n\t") );

                        DigiDump( DIGIRXTRACE, ( "-%02x", Temp[i]) );
                     }
                     DigiDump( DIGIRXTRACE, ("\n") );
                  }
#endif
                  //
                  // We have satisfied this current request, so lets
                  // complete it.
                  //
                  DigiDump( DIGIEVENT, ("---------  Read complete.  Successfully completing Irp.\n") );

                  DigiDump( DIGIEVENT, ("---------  #bytes completing = %d\n",
                                        Irp->IoStatus.Information ) );

                  DeviceExt->ReadStatus = SERIAL_COMPLETE_READ_COMPLETE;

                  DigiTryToCompleteIrp( DeviceExt, &OldIrql,
                                        STATUS_SUCCESS, ReadQueue,
                                        &DeviceExt->ReadRequestIntervalTimer,
                                        &DeviceExt->ReadRequestTotalTimer,
                                        StartReadRequest );

                  goto ReadDone; // skip DEC and unlock
               } // else ReadRxBuffer != SUCCESS
               DIGI_DEC_REFERENCE( Irp );
            } // else ReadStatus != STATUS_PENDING || IRP not started
            KeReleaseSpinLockFromDpcLevel( &DeviceExt->ControlAccess );
ReadDone:;
         }
         else // empty(RQ)
         {
            PSERIAL_XOFF_COUNTER Xc;

            //
            // We don't have an outstanding read request, so make sure
            // we reset the IDATA flag on the controller.
            //
            ChInfo = (PFEP_CHANNEL_STRUCTURE)(ControllerExt->VirtualAddress +
                                              DeviceExt->ChannelInfo.Offset);

            EnableWindow( ControllerExt, DeviceExt->ChannelInfo.Window );
            WRITE_REGISTER_UCHAR( &ChInfo->idata, TRUE );
            DisableWindow( ControllerExt );

            DigiDump( DIGIEVENT, ("---------  No outstanding read IRP's to place received data.\n") );

            DeviceExt->PreviousRxChar = (ULONG)Rin;

            // The perception of receive data might complete an XOFF_COUNTER on the WriteQueue.
            // Keep track of what we've eaten via XcPreview to avoid counting bytes twice (in ReadRxBuffer).
            Xc = DeviceExt->pXoffCounter;
            if( Xc )
            {
               RxSize = (Rin - Rout) & Rmax;

               if( RxSize < Xc->Counter )
               {
                  DigiDump( (DIGIWRITE|DIGIDIAG1), ("IDATA reduced XOFF_COUNTER\n") );
                  Xc->Counter -= RxSize;
                  DeviceExt->XcPreview += RxSize;
               }
               else
               {
                  // XOFF_COUNTER is complete.

                  KIRQL OldIrql = DISPATCH_LEVEL;
#if DBG
                  Xc->Counter = 0; // Looks a little nicer...
#endif
                  DigiDump( (DIGIWRITE|DIGIDIAG1), ("IDATA on empty(RQ) is completing XOFF_COUNTER\n") );
                  DigiTryToCompleteIrp( DeviceExt, &OldIrql, STATUS_SUCCESS,
                        &DeviceExt->WriteQueue, NULL, &DeviceExt->WriteRequestTotalTimer, StartWriteRequest );
                  goto XcDone; // skip unlock
               }
            }
            KeReleaseSpinLockFromDpcLevel( &DeviceExt->ControlAccess );
XcDone:;
         }
      } // FEP_RX_PRESENT

      if( Event.Flags & FEP_MODEM_CHANGE_SIGNAL )
      {
         ULONG WaitMask;
         UCHAR ChangedModemState;

         ChangedModemState = Event.CurrentModem ^ Event.PreviousModem;

         KeAcquireSpinLockAtDpcLevel( &DeviceExt->ControlAccess );

         WaitMask = DeviceExt->WaitMask;

         DigiDump( (DIGIMODEM|DIGIEVENT|DIGIWAIT),
                     ("---------  Modem Change Event (%s:%d)\t",
                      "   ChangedModemState = 0x%x\n",
                      ChangedModemState,
                      __FILE__, __LINE__ ) );

         if( (WaitMask & SERIAL_EV_CTS) &&
             (ControllerExt->ModemSignalTable[CTS_SIGNAL] & ChangedModemState) )
         {
            EventReason |= SERIAL_EV_CTS;
         }
         if( (WaitMask & SERIAL_EV_DSR) &&
             (ControllerExt->ModemSignalTable[DSR_SIGNAL] & ChangedModemState) )
         {
            EventReason |= SERIAL_EV_DSR;
         }
         if( (WaitMask & SERIAL_EV_RLSD) &&
             (ControllerExt->ModemSignalTable[DCD_SIGNAL] & ChangedModemState) )
         {
            EventReason |= SERIAL_EV_RLSD;
         }
         if( (WaitMask & SERIAL_EV_RING) &&
             (ControllerExt->ModemSignalTable[RI_SIGNAL] & ChangedModemState) )
         {
            EventReason |= SERIAL_EV_RING;
         }

         if( DeviceExt->EscapeChar )
         {
            UCHAR MSRByte, CurrentModemSignals;

            if( DeviceExt->PreviousMSRByte )
               DigiDump( DIGIERRORS, ("   PreviousMSRByte != 0\n") );

            MSRByte = 0;

            if( ControllerExt->ModemSignalTable[CTS_SIGNAL] & ChangedModemState )
            {
               MSRByte |= SERIAL_MSR_DCTS;
            }
            if( ControllerExt->ModemSignalTable[DSR_SIGNAL] & ChangedModemState )
            {
               MSRByte |= SERIAL_MSR_DDSR;
            }
            if( ControllerExt->ModemSignalTable[RI_SIGNAL] & ChangedModemState )
            {
               MSRByte |= SERIAL_MSR_TERI;
            }
            if( ControllerExt->ModemSignalTable[DCD_SIGNAL] & ChangedModemState )
            {
               MSRByte |= SERIAL_MSR_DDCD;
            }

            CurrentModemSignals = DeviceExt->CurrentModemSignals;
            if( ControllerExt->ModemSignalTable[CTS_SIGNAL] & CurrentModemSignals )
            {
               MSRByte |= SERIAL_MSR_CTS;
            }
            if( ControllerExt->ModemSignalTable[DSR_SIGNAL] & CurrentModemSignals )
            {
               MSRByte |= SERIAL_MSR_DSR;
            }
            if( ControllerExt->ModemSignalTable[RI_SIGNAL] & CurrentModemSignals )
            {
               MSRByte |= SERIAL_MSR_RI;
            }
            if( ControllerExt->ModemSignalTable[DCD_SIGNAL] & CurrentModemSignals )
            {
               MSRByte |= SERIAL_MSR_DCD;
            }

            if( !IsListEmpty( &DeviceExt->ReadQueue ) )
            {
               PIRP Irp;
               PIO_STACK_LOCATION IrpSp;

               Irp = CONTAINING_RECORD( DeviceExt->ReadQueue.Flink,
                                        IRP,
                                        Tail.Overlay.ListEntry );

               IrpSp = IoGetCurrentIrpStackLocation( Irp );

               if( (IrpSp->Parameters.Read.Length - Irp->IoStatus.Information) > 3 )
               {
                  PUCHAR ReadBuffer;

                  ReadBuffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer +
                               Irp->IoStatus.Information;

                  ReadBuffer[0] = DeviceExt->EscapeChar;
                  ReadBuffer[1] = SERIAL_LSRMST_MST;
                  ReadBuffer[2] = MSRByte;
                  Irp->IoStatus.Information += 3;

                  DeviceExt->PreviousMSRByte = 0;

                  DigiDump( DIGIMODEM, ("      CurrentModemSignals = 0x%x\n"
                                        "      ChangedModemState = 0x%x\n"
                                        "      MSRByte = 0x%x\n",
                                        DeviceExt->CurrentModemSignals,
                                        ChangedModemState,
                                        MSRByte) );
               }
               else
               {
                  DigiDump( (DIGIMODEM|DIGIERRORS),
                            ("Insufficient read IRP space available to record modem status change!\n") );
                  DeviceExt->PreviousMSRByte = MSRByte;
               }
            }
            else
            {
               DigiDump( (DIGIMODEM|DIGIERRORS),
                         ("No read IRP in which to record modem status change!\n") );
               DeviceExt->PreviousMSRByte = MSRByte;
            }
            KeReleaseSpinLockFromDpcLevel( &DeviceExt->ControlAccess );

            //
            // We need to read any data which may be available.
            //
            Event.Flags &= ~FEP_MODEM_CHANGE_SIGNAL;
            goto GetReceivedData;
         }
         else
         {
            KeReleaseSpinLockFromDpcLevel( &DeviceExt->ControlAccess );
         }
      } // FEP_MODEM_CHANGE_SIGNAL

      if( Event.Flags & FEP_RECEIVE_BUFFER_OVERRUN )
      {
         KeAcquireSpinLockAtDpcLevel( &DeviceExt->ControlAccess );
         DeviceExt->ErrorWord |= SERIAL_ERROR_QUEUEOVERRUN;
         InterlockedIncrement(&DeviceExt->PerfData.BufferOverrunErrorCount);
         KeReleaseSpinLockFromDpcLevel( &DeviceExt->ControlAccess );
      }

      if( Event.Flags & FEP_UART_RECEIVE_OVERRUN )
      {
         KeAcquireSpinLockAtDpcLevel( &DeviceExt->ControlAccess );
         DeviceExt->ErrorWord |= SERIAL_ERROR_OVERRUN;
         InterlockedIncrement(&DeviceExt->PerfData.SerialOverrunErrorCount);
         KeReleaseSpinLockFromDpcLevel( &DeviceExt->ControlAccess );
      }

      if( EventReason )
         DigiSatisfyEvent( ControllerExt, DeviceExt, EventReason );

   }

   //
   // Regardless of whether we processed the event, make sure we forward
   // the event out pointer.
   //
   EnableWindow( ControllerExt, ControllerExt->Global.Window );

   WRITE_REGISTER_USHORT( (PUSHORT)((PUCHAR)ControllerExt->VirtualAddress+FEP_EOUT),
                          Eout );

   DisableWindow( ControllerExt );

   DigiDump( (DIGIFLOW|DIGIEVENT), ("Exiting DigiServiceEvent\n") );

}  // DigiServiceEvent
Beispiel #7
0
NTSTATUS DispatchControl(PDEVICE_OBJECT fdo, PIRP Irp)
{							// DispatchControl
	PAGED_CODE();
	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

	NTSTATUS status;

	ULONG info = 0;

	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
	ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength;
	ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength;
	ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;

	switch (code)
	{						// process request
	case IOCTL_READ_BASE_BAR0:
		{
			ULONG offset = *(ULONG*)(Irp->AssociatedIrp.SystemBuffer);
			PUCHAR buff = (PUCHAR)ExAllocatePool(NonPagedPool,cbout);
			READ_REGISTER_BUFFER_UCHAR((PUCHAR)pdx->MemBar0+offset,buff,cbout);
			RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, buff, cbout);
			ExFreePool(buff);
			info = cbout;
			break;
		}
	case IOCTL_WRITE_BASE_BAR0:
		{
			int* tempPointer = (int*)Irp->AssociatedIrp.SystemBuffer;
			ULONG offset = *(ULONG*)(tempPointer);
			tempPointer++;
			PUCHAR buff = *(PUCHAR*)(tempPointer);
			tempPointer++;
			ULONG nInputNumber = *(ULONG*)(tempPointer);
			WRITE_REGISTER_BUFFER_UCHAR((PUCHAR)pdx->MemBar0+offset,buff,nInputNumber);
			break;
		}
	case IOCTL_READ_BASE_BAR2:
		{
			ULONG offset = *(ULONG*)(Irp->AssociatedIrp.SystemBuffer);
			PUCHAR buff = (PUCHAR)ExAllocatePool(NonPagedPool,cbout);
			READ_PORT_BUFFER_UCHAR(pdx->portbase+offset,buff,cbout);
			RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, buff, cbout);
			ExFreePool(buff);
			info = cbout;
			break;
		}
	case IOCTL_WRITE_BASE_BAR2:
		{
			int* tempPointer = (int*)Irp->AssociatedIrp.SystemBuffer;
			ULONG offset = *(ULONG*)(tempPointer);
			tempPointer++;
			PUCHAR buff = *(PUCHAR*)(tempPointer);
			tempPointer++;
			ULONG nInputNumber = *(ULONG*)(tempPointer);
			WRITE_PORT_BUFFER_UCHAR(pdx->portbase+offset,buff,nInputNumber);
			break;
		}
	case IOCTL_READ_IMAGE:
		{
			
			PUCHAR buff = (PUCHAR)ExAllocatePool(NonPagedPool,cbout);
			READ_REGISTER_BUFFER_UCHAR((PUCHAR)pdx->MemForImage,buff,cbout);
			RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, buff, cbout);
			ExFreePool(buff);
			info = cbout;
			break; 
		}
	case IOCTL_WRITE_IMAGE:
		{
			PUCHAR buff = (PUCHAR)ExAllocatePool(NonPagedPool,cbin);
			RtlCopyMemory(buff,Irp->AssociatedIrp.SystemBuffer,cbin);
			WRITE_REGISTER_BUFFER_UCHAR((PUCHAR)pdx->MemForImage,buff,cbin);
			ExFreePool(buff);
			info = cbin;
			break; 
		}
	case IOCTL_ENABLE_INT:
		{
			//允许中断
			UCHAR HSR = READ_PORT_UCHAR(pdx->portbase);
			HSR = HSR & 0xFB;
			WRITE_PORT_UCHAR(pdx->portbase,HSR);
			break;
		}

	case IOCTL_DISABLE_INT:
		{
			//关中断
			UCHAR HSR  = READ_PORT_UCHAR(pdx->portbase);
			HSR = HSR | 0x4;
			WRITE_PORT_UCHAR(pdx->portbase,HSR);
			break;
		}

	default:
		status = STATUS_INVALID_DEVICE_REQUEST;
		break;

	}						// process request

	return CompleteRequest(Irp, status, info);
}