Exemplo n.º 1
0
USHORT
NTAPI
ScsiPortReadRegisterUshort(
    IN PUSHORT Register)
{
    return READ_REGISTER_USHORT(Register);
}
Exemplo n.º 2
0
USHORT
NTAPI
VideoPortReadRegisterUshort(
    PUSHORT Register)
{
    return READ_REGISTER_USHORT(Register);
}
Exemplo n.º 3
0
USHORT
ScsiPortReadRegisterUshort(
    IN PUSHORT Register
)

/*++

Routine Description:

    Read from the specified register address.

Arguments:

    Register - Supplies a pointer to the register address.

Return Value:

    Returns the value read from the specified register address.

--*/

{

    return(READ_REGISTER_USHORT(Register));

}
Exemplo n.º 4
0
USHORT
HWREG<USHORT>::Read(
    VOID
    )
{
    volatile USHORT *addr = &m_Value;
    USHORT v = READ_REGISTER_USHORT((PUSHORT)addr);
    return v;
}
Exemplo n.º 5
0
UCHAR
HalpAcknowledgeMikasaPciInterrupt(
    PVOID ServiceContext
    )
/*++

Routine Description:

    Acknowledge the PCI interrupt.  Return the vector number of the 
    highest priority pending interrupt.

Arguments:

    ServiceContext - Service context of the interrupt service supplies
                     a pointer to the Mikasa PCI interrupt register QVA.

Return Value:

    Return the value of the highest priority pending interrupt.

--*/
{
    UCHAR InterruptVector = 0;
    USHORT IrContents;
    int i;

    //
    // Find the first zero bit in the register, starting from the highest 
    // order bit.  This implies a priority ordering that makes a certain 
    // amount of sense, in that bits 14 and 13 indicate temperature and 
    // power faults, while bit 12 is the Ncr53c810.  Note that it's 
    // necessary to add one to the bit number to make the interrupt 
    // vector, a unit-origin value in the pin-to-line table.  We do
    // this by starting i at 16 and ending it at 1; that means zero
    // is a non-enabled interrupt indication.
    //

    //
    // First, get and complement the interrupt register, so that the 
    // pending interrupts will be the "1" bits.  Then mask with the
    // enabled mask, HalpMikasaPciInterruptMask;
    //

    IrContents = ~(0xffff & READ_REGISTER_USHORT( (PUSHORT)ServiceContext ));
    IrContents &= HalpMikasaPciInterruptMask;

    for (i = 16; i >= 1; i-- ) {
        if ( IrContents & 0x8000 ) {
            InterruptVector = i;
            break;
        } else {
            IrContents <<= 1;
        }
    }
    return( InterruptVector );

}
Exemplo n.º 6
0
UCHAR
NTAPI
LlbHwOmap3TwlRead1(IN UCHAR ChipAddress,
                   IN UCHAR RegisterAddress)
{
    volatile int i = 1000;
        
    /* Select the register */
    LlbHwOmap3TwlWrite(ChipAddress, RegisterAddress, 0, NULL);

    /* Now read it */
    WRITE_REGISTER_USHORT(0x48070024, 0x8401);
    for (i = 1000; i > 0; i--);
    return READ_REGISTER_USHORT(0x4807001c);
}
Exemplo n.º 7
0
NDIS_STATUS
CardInitialize(
    IN PHTDSU_ADAPTER       Adapter,
    IN BOOLEAN              PerformSelfTest
    )

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Functional Description:

    This routine will attempt to initialize the controller, but will not
    enable transmits or receives.

Parameters:

    Adapter _ A pointer ot our adapter information structure.

    PerformSelfTest _ TRUE if caller wants to run selftest diagnostics.
                      This normally takes about 4 seconds to complete, so you
                      wouldn't want to do it every time you start up.

Return Values:

    NDIS_STATUS_HARD_ERRORS
    NDIS_STATUS_SUCCESS

---------------------------------------------------------------------------*/

{
    DBG_FUNC("CardInitialize")

    NDIS_STATUS Status;

    USHORT      SelfTestStatus;

    UINT        TimeOut;

    DBG_ENTER(Adapter);

    /*
    // First we make sure the adapter is where we think it is.
    */
    Status = CardIdentify(Adapter);
    if (Status != NDIS_STATUS_SUCCESS)
    {
        return (Status);
    }

    /*
    // Reset the hardware to make sure we're in a known state.
    */
    Status = CardDoCommand(Adapter, 0, HTDSU_CMD_RESET);
    
    if (PerformSelfTest)
    {
        /*
        // Wait for the reset to complete before starting the self-test.
        // Then issue the self-test command to see if the adapter firmware
        // is happy with the situation.
        */
        Status = CardDoCommand(Adapter, 0, HTDSU_CMD_SELFTEST);
        if (Status != NDIS_STATUS_SUCCESS)
        {
            DBG_ERROR(Adapter,("Failed HTDSU_CMD_RESET\n"));
            /*
            // Log error message and return.
            */
            NdisWriteErrorLogEntry(
                    Adapter->MiniportAdapterHandle,
                    NDIS_ERROR_CODE_HARDWARE_FAILURE,
                    3,
                    Status,
                    __FILEID__,
                    __LINE__
                    );
            return (Status);
        }
        
        /*
        // Wait for the self test to complete, but don't wait forever.
        */
        TimeOut = 0;
        while (Status == NDIS_STATUS_SUCCESS &&
               READ_REGISTER_USHORT(&Adapter->AdapterRam->Command) !=
                        HTDSU_CMD_NOP)
        {
            if (TimeOut++ > HTDSU_SELFTEST_TIMEOUT)
            {
                DBG_ERROR(Adapter,("Timeout waiting for SELFTEST to complete\n"));
                Status = NDIS_STATUS_HARD_ERRORS;
            }
            else
            {
                NdisStallExecution(_100_MICROSECONDS);
            }
        }
        if (Status != NDIS_STATUS_SUCCESS)
        {
            DBG_ERROR(Adapter,("Failed HTDSU_CMD_SELFTEST\n"));
            /*
            // Log error message and return.
            */
            NdisWriteErrorLogEntry(
                    Adapter->MiniportAdapterHandle,
                    NDIS_ERROR_CODE_HARDWARE_FAILURE,
                    3,
                    Status,
                    __FILEID__,
                    __LINE__
                    );
            return (Status);
        }

        /*
        // Verify that self test was successful.
        */
        SelfTestStatus = READ_REGISTER_USHORT(&Adapter->AdapterRam->SelfTestStatus);
        if (SelfTestStatus != 0 && SelfTestStatus != HTDSU_SELFTEST_OK)
        {
            DBG_ERROR(Adapter,("Failed HTDSU_CMD_SELFTEST (Status=%X)\n",
                      SelfTestStatus));
            /*
            // Log error message and return.
            */
            NdisWriteErrorLogEntry(
                    Adapter->MiniportAdapterHandle,
                    NDIS_ERROR_CODE_HARDWARE_FAILURE,
                    3,
                    SelfTestStatus,
                    __FILEID__,
                    __LINE__
                    );
            return (NDIS_STATUS_HARD_ERRORS);
        }
    }

    DBG_LEAVE(Adapter);

    return (NDIS_STATUS_SUCCESS);
}
Exemplo n.º 8
0
NDIS_STATUS
CardDoCommand(
    IN PHTDSU_ADAPTER       Adapter,
    IN USHORT               CardLine,   /* HTDSU_CMD_LINE1 or HTDSU_CMD_LINE2 */
    IN USHORT               CommandValue
    )

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Functional Description:

    This routine routine will execute a command on the card after making
    sure the previous command has completed properly.

Parameters:

    Adapter _ A pointer ot our adapter information structure.

    CardLine _ Specifies which line to use for the transmit (HTDSU_LINEx_ID).

    CommandValue _ HTDSU_CMD_??? command to be executed.

Return Values:

    NDIS_STATUS_SUCCESS
    NDIS_STATUS_HARD_ERRORS

---------------------------------------------------------------------------*/
{
    DBG_FUNC("CardDoCommand")

    ULONG       TimeOut = 0;

    DBG_ENTER(Adapter);
    DBG_FILTER(Adapter, DBG_PARAMS_ON,("Line=%d, Command=%04X, LineStatus=%Xh\n",
                CardLine, CommandValue,
                READ_REGISTER_USHORT(&Adapter->AdapterRam->StatusLine1)
                ));

    /*
    // Wait for command register to go idle - but don't wait too long.
    // If we timeout here, there's gotta be something wrong with the adapter.
    */
    while ((READ_REGISTER_USHORT(&Adapter->AdapterRam->Command) != 
                    HTDSU_CMD_NOP) ||
           (READ_REGISTER_USHORT(&Adapter->AdapterRam->CoProcessorId) != 
                    HTDSU_COPROCESSOR_ID))
    {
        if (TimeOut++ > HTDSU_SELFTEST_TIMEOUT)
        {
            DBG_ERROR(Adapter,("Timeout waiting for %04X command to clear\n",
                      READ_REGISTER_USHORT(&Adapter->AdapterRam->Command)));
            /*
            // Ask for reset, and disable interrupts until we get it.
            */
            Adapter->NeedReset = TRUE;
            Adapter->InterruptEnableFlag = HTDSU_INTR_DISABLE;
            CardDisableInterrupt(Adapter);
            
            return (NDIS_STATUS_HARD_ERRORS);
        }
        NdisStallExecution(_100_MICROSECONDS);
    }
    DBG_NOTICE(Adapter,("Timeout=%d waiting to submit %04X\n",
               TimeOut, CommandValue));

    /*
    // Before starting a reset command, we clear the the co-processor ID
    // which then gets set to the proper value when the reset is complete.
    */
    if (CommandValue == HTDSU_CMD_RESET)
    {
        WRITE_REGISTER_USHORT(&Adapter->AdapterRam->CoProcessorId, 0);
    }

    /*
    // Send the command to the adapter.
    */
    WRITE_REGISTER_USHORT(
            &Adapter->AdapterRam->Command,
            (USHORT) (CommandValue + CardLine)
            );

    DBG_LEAVE(Adapter);

    return (NDIS_STATUS_SUCCESS);
}
Exemplo n.º 9
0
NTSTATUS
SerialCreate( IN PDEVICE_OBJECT DeviceObject,
              IN PIRP Irp )
/*++

Routine Description:


Arguments:


Return Value:


--*/
{
   PDIGI_DEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
   PDIGI_CONTROLLER_EXTENSION ControllerExt = DeviceExt->ParentControllerExt;

   NTSTATUS Status=STATUS_SUCCESS;

   PFEP_CHANNEL_STRUCTURE ChInfo;

   DIGI_XFLAG IFlag;
   USHORT Rmax, Tmax, Rhigh;
   KIRQL OldIrql;
   UCHAR MStatSet, MStatClear, HFlowSet, HFlowClear;

#if DBG
   LARGE_INTEGER CurrentSystemTime;
#endif

   if (DeviceObject==ControllerExt->ControllerDeviceObject)
   {
      /*
      ** All controller opens succeed.
      */
      DigiDump( (DIGIIRP|DIGIFLOW|DIGICREATE), ("ControllerCreate\n"));
      Irp->IoStatus.Status = STATUS_SUCCESS;
      Irp->IoStatus.Information = 0;
      DigiIoCompleteRequest( Irp, IO_NO_INCREMENT );
      return STATUS_SUCCESS;
   }

#if DBG
   KeQuerySystemTime( &CurrentSystemTime );
#endif
   DigiDump( (DIGIIRP|DIGIFLOW|DIGICREATE), ("Entering SerialCreate: port = %s\tIRP = 0x%x\t%u:%u\n",
                                             DeviceExt->DeviceDbgString, Irp, CurrentSystemTime.HighPart, CurrentSystemTime.LowPart) );

   ASSERT( IoGetCurrentIrpStackLocation(Irp)->MajorFunction == IRP_MJ_CREATE );

   InterlockedIncrement(&ControllerExt->PerfData.OpenRequests);

   KeAcquireSpinLock( &DeviceExt->ControlAccess, &OldIrql );

   DeviceExt->DeviceState = DIGI_DEVICE_STATE_OPEN;
   DeviceExt->WaitMask = 0L;
   DeviceExt->HistoryWait = 0L;
   DeviceExt->TotalCharsQueued = 0L;
   DeviceExt->EscapeChar = 0;
   DeviceExt->SpecialFlags = 0;
   DeviceExt->UnscannedRXFLAGPosition = MAXULONG;

   KeReleaseSpinLock( &DeviceExt->ControlAccess, OldIrql );

   //
   // Okay, lets make sure the port on the controller is in a known
   // state.
   //

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

   FlushTransmitBuffer( ControllerExt, DeviceExt );
   FlushReceiveBuffer( ControllerExt, DeviceExt );

   // Set default flow control limits.
   EnableWindow( ControllerExt, DeviceExt->ChannelInfo.Window );
   Rmax = READ_REGISTER_USHORT( &ChInfo->rmax );
   Tmax = READ_REGISTER_USHORT( &ChInfo->tmax );
   DisableWindow( ControllerExt );

   DeviceExt->XonLimit = (((LONG)Rmax + 1) / 4);
   Rhigh = Rmax - (USHORT)DeviceExt->XonLimit;
   DeviceExt->XoffLimit = DeviceExt->XonLimit;	// We preserve XoffLimit in Win32 semantics
   WriteCommandWord( DeviceExt, SET_RCV_LOW, (USHORT)DeviceExt->XonLimit );
   WriteCommandWord( DeviceExt, SET_RCV_HIGH, Rhigh );
   WriteCommandWord( DeviceExt, SET_TX_LOW, (USHORT)((Tmax + 1) / 4) );

   //
   // Based on 10ms polling frequency and 115.2Kbps bit rate,
   // we acquire up to 115.2 bytes per polling iteration.
   // Thus, to avoid flow control, we need notification up to
   // two polling iterations prior to reaching XoffLimit.
   // However, we need at least 50 bytes to make the interaction worthwhile.
   // DH Calculate limit dynamically based on communication characteristics.
   //
   if( Rhigh > 2*115 + 50 )
      DeviceExt->ReceiveNotificationLimit = Rhigh - 2*115;
   else
   if( Rmax >= 100 )
      DeviceExt->ReceiveNotificationLimit = 50;
   else // shouldn't happen
      DeviceExt->ReceiveNotificationLimit = Rmax / 2;

   //
   // Initialize requested queue sizes.
   //
   DeviceExt->RequestedQSize.InSize = (ULONG)(Rmax + 1);
   DeviceExt->RequestedQSize.OutSize = (ULONG)(Tmax + 1);

   //
   // Set where RxChar and RxFlag were last seen in the buffer to a
   // bogus value so we catch the condition where the 1st character in
   // is RxFlag, and so we give notification for the 1st character
   // received.
   //
   DeviceExt->PreviousRxChar = MAXULONG;
   DeviceExt->UnscannedRXFLAGPosition = MAXULONG;

   //
   // Set the Xon & Xoff characters for this device to default values.
   //

   WriteCommandBytes( DeviceExt, SET_XON_XOFF_CHARACTERS,
                      DEFAULT_XON_CHAR, DEFAULT_XOFF_CHAR );

   MStatClear = MStatSet = 0;
   HFlowClear = HFlowSet = 0;

   //
   // We have some RTS flow control to worry about.
   //
   // Don't forget that flow control is sticky across
   // open requests.
   //
   if( (DeviceExt->FlowReplace & SERIAL_RTS_MASK) ==
       SERIAL_RTS_HANDSHAKE )
   {
      //
      // This is normal RTS input flow control
      //
      HFlowSet |= ControllerExt->ModemSignalTable[RTS_SIGNAL];
   }
   else if( (DeviceExt->FlowReplace & SERIAL_RTS_MASK) ==
            SERIAL_RTS_CONTROL )
   {
      //
      // We need to make sure RTS is asserted when certain 'things'
      // occur, or when we are in a certain state.
      //
      MStatSet |= ControllerExt->ModemSignalTable[RTS_SIGNAL];
   }
   else if( (DeviceExt->FlowReplace & SERIAL_RTS_MASK) ==
            SERIAL_TRANSMIT_TOGGLE )
   {
   }
   else
   {
      //
      // RTS Control Mode is in a Disabled state.
      //
      MStatClear |= ControllerExt->ModemSignalTable[RTS_SIGNAL];
   }

   //
   // We have some DTR flow control to worry about.
   //
   // Don't forget that flow control is sticky across
   // open requests.
   //
   if( (DeviceExt->ControlHandShake & SERIAL_DTR_MASK) ==
       SERIAL_DTR_HANDSHAKE )
   {
      //
      // This is normal DTR input flow control
      //
      HFlowSet |= ControllerExt->ModemSignalTable[DTR_SIGNAL];
   }
   else if( (DeviceExt->ControlHandShake & SERIAL_DTR_MASK) ==
            SERIAL_DTR_CONTROL )
   {
      //
      // We need to make sure DTR is asserted when certain 'things'
      // occur, or when we are in a certain state.
      //
      MStatSet |= ControllerExt->ModemSignalTable[DTR_SIGNAL];

   }
   else
   {
      //
      // DTR Control Mode is in a Disabled state.
      //
      MStatClear |= ControllerExt->ModemSignalTable[DTR_SIGNAL];
   }

   //
   // CTS, DSR, and DCD output handshaking is sticky across OPEN requests.
   //
   if( (DeviceExt->ControlHandShake & SERIAL_CTS_HANDSHAKE) )
   {
      HFlowSet |= ControllerExt->ModemSignalTable[CTS_SIGNAL];
   }
   else
   {
      HFlowClear |= ControllerExt->ModemSignalTable[CTS_SIGNAL];
   }

   if( (DeviceExt->ControlHandShake & SERIAL_DSR_HANDSHAKE) )
   {
      HFlowSet |= ControllerExt->ModemSignalTable[DSR_SIGNAL];
   }
   else
   {
      HFlowClear |= ControllerExt->ModemSignalTable[DSR_SIGNAL];
   }

   if( (DeviceExt->ControlHandShake & SERIAL_DCD_HANDSHAKE) )
   {
      HFlowSet |= ControllerExt->ModemSignalTable[DCD_SIGNAL];
   }
   else
   {
      HFlowClear |= ControllerExt->ModemSignalTable[DCD_SIGNAL];
   }

   //
   // Make sure we enable/disable flow controls before trying to
   // explicitly set/clear modem control lines.
   //
   if( HFlowSet || HFlowClear )
   {
      DeviceExt->WriteOnlyModemSignalMask = (~HFlowSet) &
               (ControllerExt->ModemSignalTable[DTR_SIGNAL]|ControllerExt->ModemSignalTable[RTS_SIGNAL]);
      WriteCommandBytes( DeviceExt, SET_HDW_FLOW_CONTROL,
                         HFlowSet, HFlowClear );
   }

   if( MStatSet || MStatClear )
   {
      DeviceExt->CurrentModemSignals |= MStatSet;
      DeviceExt->CurrentModemSignals &= ~MStatClear;
      DeviceExt->WriteOnlyModemSignalValue |= MStatSet;
      DeviceExt->WriteOnlyModemSignalValue &= ~MStatClear;

      WriteCommandBytes( DeviceExt, SET_MODEM_LINES,
                         MStatSet, MStatClear );
   }

   //
   // Make sure we get break notification through the event queue to
   // begin with.
   //
   IFlag.Mask = (USHORT)(~( IFLAG_PARMRK | IFLAG_INPCK | IFLAG_DOSMODE ));
   IFlag.Src = IFLAG_BRKINT;
   IFlag.Command = SET_IFLAGS;
   SetXFlag( DeviceExt, &IFlag );

   //
   // Okay, were done, lets get the heck out of dodge.
   //
   Irp->IoStatus.Status = Status;
   Irp->IoStatus.Information = 0L;

   //
   // We do this check here to make sure the controller has had
   // a chance to catch up.  Running on fast machines doesn't always
   // give the controller a chance.
   //
   EnableWindow( ControllerExt, DeviceExt->ChannelInfo.Window );

   if( READ_REGISTER_USHORT( &ChInfo->rlow )
         == 0 )
      DigiDump( DIGIINIT, ("ChInfo->rlow == 0\n"));

   if( READ_REGISTER_USHORT( &ChInfo->rhigh )
         == 0 )
      DigiDump( DIGIINIT, ("ChInfo->rhigh == 0\n"));

   if( READ_REGISTER_USHORT( &ChInfo->tlow )
         == 0 )
      DigiDump( DIGIINIT, ("ChInfo->tlow == 0\n"));

   //
   // Enable IDATA so we get notified when new data has arrived.
   //
   WRITE_REGISTER_UCHAR( &ChInfo->idata, TRUE );

   DisableWindow( ControllerExt );

   DigiIoCompleteRequest( Irp, IO_NO_INCREMENT );

   InterlockedIncrement(&ControllerExt->PerfData.OpenPorts);

   DigiDump( (DIGIFLOW|DIGICREATE), ("Exiting SerialCreate: port = %s\n",
                                     DeviceExt->DeviceDbgString) );
   return( STATUS_SUCCESS );
}  // end SerialCreate
Exemplo n.º 10
0
USHORT NBytesInRecvBuffer( PDIGI_CONTROLLER_EXTENSION ControllerExt,
                           PDIGI_DEVICE_EXTENSION DeviceExt )
/*++

Routine Description:

   Determine the number of actual bytes in the receive buffer.  This routine
   takes into account DOSMODE on the controller.

Arguments:

   ControllerExt - pointer to the controller extension information
                   assosicated with DeviceExt.

   DeviceExt - pointer to the device specific information.

Return Value:

   Number of bytes in the receive buffer.

--*/
{
   PUCHAR ControllerBuffer;
   PFEP_CHANNEL_STRUCTURE ChInfo;
   USHORT AmountInQueue;
   USHORT Rin, Rout, Rmax;
   USHORT DosMode;
   UCHAR ReceivedByte, SecondReceivedByte;

   ControllerBuffer = ControllerExt->VirtualAddress + DeviceExt->RxSeg.Offset;

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

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

   DosMode &= IFLAG_DOSMODE;

   if( !DosMode )
   {
      AmountInQueue = Rin - Rout;
      if( (SHORT)AmountInQueue < 0)
         AmountInQueue += (Rmax + 1);

      return( AmountInQueue );
   }

   AmountInQueue = 0;

   EnableWindow( ControllerExt, DeviceExt->RxSeg.Window );

   DigiDump( DIGIIOCTL,
             ("      NRecvRoutine: Rin = 0x%x, Rout = 0x%x\n",
              Rin,
              Rout) );

   while( Rout != Rin )
   {
      ReceivedByte = READ_REGISTER_UCHAR( (ControllerBuffer + Rout) );

      Rout++;
      Rout &= Rmax;
      AmountInQueue++;

      DigiDump( DIGIIOCTL,
                ("      NRecvByte = 0x%x, Rout = 0x%x\n",
                 ReceivedByte,
                 Rout) );

      //
      // We need to process out DigiBoard specific 0xFF.
      //
      if( ReceivedByte == 0xFF )
      {
         //
         // We have some special processing to do!
         //

         //
         // Is there a second character available??
         //
         if( Rout == Rin )
         {
            //
            // The second character isn't available!
            //
            AmountInQueue--;
            DigiDump( DIGIIOCTL,
                      ("      NRecvRoutine, 2nd byte not available!\n" ) );

            break;
         }
         else
         {
            //
            // Get the 2nd characters
            //
            SecondReceivedByte = READ_REGISTER_UCHAR( (ControllerBuffer + Rout) );
            Rout++;
            Rout &= Rmax;

            if( SecondReceivedByte == 0xFF )
            {
               //
               // We actually received a 0xFF in the data stream.
               //
               DigiDump( DIGIIOCTL,
                         ("      NRecvRoutine, Actually recv'ed 0xFF\n" ) );
               continue;

            }
            else
            {
               //
               // This is Line Status information.  Is the last
               // character available??
               //
               if( Rin == Rout )
               {
                  //
                  // The 3rd byte isn't available
                  //
                  AmountInQueue--;
                  DigiDump( DIGIIOCTL,
                            ("      NRecvRoutine, 3rd byte not available!\n" ) );
                  break;
               }

               Rout++;
               Rout &= Rmax;

            }

         }
      }
   }

   DisableWindow( ControllerExt );

   DigiDump( DIGIIOCTL,
             ("      NRecvRoutine, return RecvBytes = %d!\n",
              AmountInQueue ) );
   return( AmountInQueue );

}  // end NBytesInRecvBuffer
Exemplo n.º 11
0
UCHAR
HalpAcknowledgeNoritakePciInterrupt(
    PVOID ServiceContext
    )
/*++

Routine Description:

    Acknowledge the PCI interrupt.  Return the vector number of the
    highest priority pending interrupt.

Arguments:

    ServiceContext - Service context of the interrupt service supplies
                     a pointer to the Noritake PCI interrupt register 1 QVA.

Return Value:

    Return the value of the highest priority pending interrupt.

--*/
{
    UCHAR InterruptVector = 0;
    USHORT IrContents;
    int i;

    //
    // Interrupt1 register contains the sum of all interrupts of Interrupt2
    // and Interrupt3 registers in bit 0. The rest of the register contains
    // the A and B interrupts of the 7 PCI slots.  Interrupt2 register
    // contains the sum of all of the unmasked interrupts of Interrupt 2 in bit
    // 0.  Bit 1 is asserted when any secondary PCI bus interrupt is asserted
    // (including those in interrupt register 1) and the posted write buffers
    // in the PPB have been flushed.  The rest of the register contians the C
    // and D interrupts of all of the slots.  Interrupt3 register contains some
    // safety and reliability interrupts.  Please see mikasa.h for the
    // definitions of which interrupt is at which bit in the register.
    //
    // Each bit in the registers corresponds to an interrupt vector (which
    // will later have PCI_VECTORS added to it.)  This vector can be obtained
    // by adding the vector offset for that register to the bit position.
    // These offsets are also defined in mikasa.h.
    //
    // All registers are "reverse-logic" (active low), where a 0 means that an
    // interrupt is waiting.  That is why we must complement the contents of
    // the register before we mask with HalpNoritakePciInterruptXMask.
    //

    //
    // First, get and complement the first interrupt register, so that the
    // pending interrupts will be the "1" bits.  Then mask with the
    // enabled mask, HalpNoritakePciInterrupt1Mask;
    //

    IrContents = 
            ~(0xffff & READ_REGISTER_USHORT((PUSHORT)HalpNoritakePciIr1Qva));
    IrContents &= HalpNoritakePciInterrupt1Mask;

    //
    // Position bit 1 as the lowest bit.  We will start checking here - this
    // is the first "real" interrupt.
    //

    IrContents >>= 1;

    for( i = 1; i < 16; i++ ) {
        if( IrContents & 0x1 ) {
            InterruptVector = i + REGISTER_1_VECTOR_OFFSET;
            break;
        }
        IrContents >>= 1;
    }


    if( InterruptVector == 0 ) {

        //
        // We didn't find any interrupts in interrupt register 1.
        // Check interrupt register 2.
        //

        IrContents = 
            ~(0xffff & READ_REGISTER_USHORT((PUSHORT)HalpNoritakePciIr2Qva));
        IrContents &= HalpNoritakePciInterrupt2Mask;

        //
        // Position bit 2 in the lowest bit.  We will start checking here -
        // this is the first "real" interrupt.
        //

        IrContents >>= 2;

        for( i = 2; i < 16; i++ ) {
            if( IrContents & 0x1 ) {
                InterruptVector = i + REGISTER_2_VECTOR_OFFSET;
                break;
            }
            IrContents >>= 1;
        }

        if( InterruptVector == 0 ) {

            //
            // We didn't find any interrupts in interrupt register 2.
            // Check Interrupt Register 3.
            //

            IrContents = ~(0xffff &
                     READ_REGISTER_USHORT((PUSHORT)HalpNoritakePciIr3Qva));
            IrContents &= HalpNoritakePciInterrupt3Mask;

            //
            // Position bit 2 in the lowest bit.  We will start checking here -
            // this is the first "real" interrupt.
            //

            IrContents >>= 2;

            for( i = 2; i < 6; i++ ) {
                if( IrContents & 0x1 ) {
                    InterruptVector = i + REGISTER_3_VECTOR_OFFSET;
                    break;
                }
                IrContents >>= 1;
            }

        }
Exemplo n.º 12
0
VOID
CardGetReceiveInfo(
    IN PHTDSU_ADAPTER       Adapter,
    OUT PUSHORT             CardLine,    /* HTDSU_CMD_LINE1 or HTDSU_CMD_LINE2 */
    OUT PUSHORT             BytesReceived,
    OUT PUSHORT             RxErrors
    )

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Functional Description:

    This routine will retrieve the packet header information from the
    receive buffer.  This assumes that the controller has notified the
    driver that a packet has been received.

Parameters:

    Adapter _ A pointer ot our adapter information structure.

    CardLine _ Specifies which line the packet was received on (HTDSU_LINEx_ID).

    BytesReceived _ Number of bytes received.

    RxErrors _ Receive error flags non-zero if packet has errors.

Return Values:

    None

---------------------------------------------------------------------------*/
{
    DBG_FUNC("CardGetReceiveInfo")

    USHORT Length;

    DBG_ENTER(Adapter);

    /*
    // This should be true if we're here, but there are race conditions
    // on hangup where I've seen this condition hit.
    */
    if (READ_REGISTER_USHORT(&Adapter->AdapterRam->RxDataAvailable) == 0)
    {
        *RxErrors = 0;
        *BytesReceived = 0;
        *CardLine = HTDSU_CMD_LINE1;    // Don't return a bad line #
    }
    else
    {
        /*
        // The length field tells us how many bytes are in the packet, and
        // the most significant bit tells us whether the packet has a CRC error.
        */
        Length = READ_REGISTER_USHORT(&Adapter->AdapterRam->RxBuffer.Length);
        *BytesReceived = Length & ~HTDSU_CRC_ERROR;
        *RxErrors = Length & HTDSU_CRC_ERROR;
        
        /*
        // The least significant nibble of the address tells us what line the
        // packet was received on -- at least it better...
        */
        *CardLine = (READ_REGISTER_USHORT(
                        &Adapter->AdapterRam->RxBuffer.Address) &
                        0x000F) + HTDSU_CMD_LINE1;

        if ((*CardLine != HTDSU_CMD_LINE1) && (*CardLine != HTDSU_CMD_LINE2))
        {
            *RxErrors |= HTDSU_RX_ERROR;
            *CardLine = HTDSU_CMD_LINE1;    // Don't return a bad line #
        }
        else if (*BytesReceived > HTDSU_MAX_PACKET_SIZE)
        {
            *RxErrors |= HTDSU_RX_ERROR;
        }
    }

    DBG_LEAVE(Adapter);
}
Exemplo n.º 13
0
VOID
HalpAcknowledgeClockInterrupt(
    VOID
    )
/*++

Routine Description:

    Acknowledge the clock interrupt from the interval timer.  The interval
    timer for Lego comes from the Dallas real-time clock.

Arguments:

    None.

Return Value:

    None.

--*/
{
    LEGO_WATCHDOG  WdRegister;
    
    static LEGO_WATCHDOG WdRegisterDbg;
    static ULONG DbgWdCnt = 0;
    static ULONG WdNextService = 0;
    static BOOLEAN WdIntervalSet = FALSE;
     
    //
    // Make watchdog service interval a function of the timer period.
    //
    
#if 1
    static ULONG WdServiceIntervals[8] = {1, 1, 5, 15, 100, 600, 3000, 20000};
#else
    static ULONG WdServiceIntervals[8] = {1, 1, 1, 1, 1, 1, 1, 1};
#endif

    //
    // Acknowledge the clock interrupt by reading the control register C of
    // the Real Time Clock.
    //

    HalpReadClockRegister( RTC_CONTROL_REGISTERC );

    //
    // If we are to service the Watchdog Timer, do it here
    //
    // Setting Phase to one will restart the timer...
    // [wem] this needs more work. For example, no need to touch it each clock tick!...
    //

    if (HalpLegoServiceWatchdog) {

        if (WdNextService==0) {

            //
            // read register to get service interval
            //

            WdRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva );
            WdNextService = WdServiceIntervals[WdRegister.TimerOnePeriod];

#if DBG
            if (!WdIntervalSet) {
                DbgPrint(" <Watchdog:%04x> ",WdRegister.All);
                DbgPrint(" <WdInterval:%d> ",WdNextService);
                WdRegisterDbg.All = WdRegister.All;
                WdIntervalSet = TRUE;
            }
#endif
        }

        WdNextService--;

        //
        // If service interval falls to zero, read register to service timer
        //

        if (WdNextService==0) {

            WdRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva );

#if DBG

            if (WdRegisterDbg.All != WdRegister.All) {
                WdRegisterDbg.All = WdRegister.All;
                DbgWdCnt = 0;
            }

            if (DbgWdCnt < 2) {
                DbgPrint(" <Watchdog:%04x> ",WdRegister.All);
            }

            if ((DbgWdCnt % 10000)==0) {
                DbgPrint(" <Watchdog:%04x> ",WdRegister.All);
                DbgWdCnt = 1;
            }

            DbgWdCnt++;
#endif

            // 
            // Reset the timer. This is done by writing 1 then 0
            // to the Watchdog register's Phase bit
            //
            // If LegoDebugWatchdogIsr is true, let watchdog timer expire.
            // This will result in a watchdog interrupt or a system reset 
            // depending on the watchdog mode.
            //

            if (!LegoDebugWatchdogIsr) {
#if 0
                if (HalpLegoWatchdogSingleMode) {
                    WdRegister.Mode = WATCHDOG_MODE_1TIMER;
                }
#endif
                WdRegister.Phase = 1;
                WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva, WdRegister.All);
                WdRegister.Phase = 0;
                WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva, WdRegister.All);
            }
        }
    }
}
Exemplo n.º 14
0
BOOLEAN
HalHandleNMI(
    IN PKINTERRUPT Interrupt,
    IN PVOID ServiceContext
    )
/*++

Routine Description:

   This function is called when an EISA NMI occurs.  It prints the 
   appropriate status information and bugchecks.

Arguments:

   Interrupt - Supplies a pointer to the interrupt object

   ServiceContext - Bug number to call bugcheck with.

Return Value:

   Returns TRUE.

--*/
{
    LEGO_SRV_MGMT  SmRegister;
    UCHAR   NmiControl, NmiStatus;
    BOOLEAN GotSerr, GotIochk, GotSmFan, GotSmTemp, GotHalt;
    
    NMIcount++;

#if DBG
    if (NMIcount<5) {
        DbgPrint("II<NMI><");
    }
    if (NMIcount % 100 == 0) {
        DbgPrint("II<NMI><%08x><", NMIcount);
    }
#endif

    GotSerr = GotIochk = GotSmFan = GotSmTemp = GotHalt = FALSE;

    //
    // Set the Eisa NMI disable bit. We do this to mask further NMI 
    // interrupts while we're servicing this one.
    //
    NmiControl = READ_PORT_UCHAR(
                    &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable);
    ((PNMI_ENABLE)(&NmiControl))->NmiDisable = 1;
    WRITE_PORT_UCHAR(
        &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, NmiControl);

#ifdef DBG
    DbgPrint("HalHandleNMI: wrote 0x%x to NmiEnable\n", NmiControl);
#endif

    NmiStatus =
        READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);

    if (NmiStatus & 0x80) {
        GotSerr = TRUE;

#ifdef DBG
        DbgPrint("HalHandleNMI: Parity Check / Parity Error\n");
        DbgPrint("HalHandleNMI:    NMI Status = 0x%x\n", NmiStatus);
#endif
        HalAcquireDisplayOwnership(NULL);
        HalDisplayString ("NMI: Parity Check / Parity Error\n");
        KeBugCheck(NMI_HARDWARE_FAILURE);
        return (TRUE);
    }

    if (NmiStatus & 0x40) {
        GotIochk = TRUE;
#ifdef DBG
        DbgPrint("HalHandleNMI: Channel Check / IOCHK\n");
        DbgPrint("HalHandleNMI:    NMI Status = 0x%x\n", NmiStatus);
#endif
        HalAcquireDisplayOwnership(NULL);
        HalDisplayString ("NMI: Channel Check / IOCHK\n");
        KeBugCheck(NMI_HARDWARE_FAILURE);
        return (TRUE);
    }

    // Read server management register
    //  Events that can be reported as NMI are:
    //      Enclosure temperature too high
    //      CPU Fan failure
    //
    // For now, generate a bugcheck.
    // [wem] Future: perform secondary dispatch to give
    //       driver shot at reporting problem.
    //
    SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva );

    GotSmFan = SmRegister.CpuFanFailureNmi == 1;
    GotSmTemp = SmRegister.EnclTempFailureNmi == 1;

    if (GotSmFan || GotSmTemp) {

#ifdef DBG
        DbgPrint("HalHandleNMI: Server management NMI\n");
        DbgPrint("HalHandleNMI:    NMI Status = 0x%x\n", NmiStatus);
        DbgPrint("HalHandleNMI:    Server Management Status = 0x%x\n", SmRegister);
#endif

        //
        // If secondary dispatch enabled, do it now.
        //
#if 0
        if (HalpLegoDispatchNmi
            && ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[SM_ERROR_VECTOR])(
                    PCR->InterruptRoutine[SM_ERROR_VECTOR],
                    TrapFrame)
           ) {
            return TRUE;
        }
#endif

        //
        // Build uncorrectable error frame and 
        // prepare for orderly shutdown
        //
        // The delayed shutdown depends on watchdog timer support
        // A power off cannot be directly done since KeBugChk() turns
        // off interrupts, so there's no way to get control back.
        //
        // WARNING: Pick a delay that allows a dump to complete.
        //

        LegoServerMgmtReportFatalError(SmRegister.All);
        LegoServerMgmtDelayedShutdown(8);                  // Issue reset in 8 seconds

        HalAcquireDisplayOwnership(NULL);

        HalDisplayString ("NMI: Hardware Failure -- ");
        HalDisplayString ((SmRegister.CpuFanFailureNmi==1) ? "CPU fan failed."
                                                           : "Enclosure termperature too high.");
        HalDisplayString ("\nSystem Power Down will be attempted in 8 seconds...\n\n");
        KeBugCheck(NMI_HARDWARE_FAILURE);
        return (TRUE);
    }


    // 
    // Halt button was hit.
    //
    // [wem] Perform second-level dispatch here too?
    //
    if (!GotSerr && !GotIochk && !GotSmFan && !GotSmTemp) {

        //
        // If secondary dispatch enabled, do it now.
        //
#if 0
        if (HalpLegoDispatchHalt
            && ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[HALT_BUTTON_VECTOR])(
                    PCR->InterruptRoutine[HALT_BUTTON_VECTOR],
                    TrapFrame)
           ) {
            return TRUE;
        }
#endif

        GotHalt = TRUE;
        HalDisplayString ("NMI: Halt button pressed.\n");

        if (HalpHaltButtonBreak) {
            DbgBreakPoint();
        }

        return (TRUE);
    }

    //
    // Clear and re-enable SERR# and IOCHK#, then re-enable NMI
    //

#ifdef DBG
    DbgPrint("HalHandleNMI: Shouldn't get here!\n");
#endif

    if (GotSerr) {
#ifdef DBG
        DbgPrint("HalHandleNMI: Resetting SERR#; NMI count = %d\n", NMIcount);
#endif
        //
        // Reset SERR# (and disable it), then re-enable it.
        //
        WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0x04);
        WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0);
    }

    if (GotIochk) {
#ifdef DBG
        DbgPrint("HalHandleNMI: Resetting IOCHK#; NMI count = %d\n", NMIcount);
#endif
        //
        // Reset IOCHK# (and disable it), then re-enable it.
        //
        WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0x08);
        WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0);
    }

    if (GotSmFan || GotSmTemp) {
        //
        // Reset Server management condition.
        //
        // Interrupt must be cleared or the NMI will continue
        // to occur.
        //
        SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva );
        if (GotSmFan) {
            SmRegister.CpuFanFailureNmi = 1;
        }
        else {
            SmRegister.EnclTempFailureNmi = 1;
        }
        WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All );
    }

    //
    // Clear the Eisa NMI disable bit. This re-enables NMI interrupts,
    // now that we're done servicing this one.
    //
    NmiControl = READ_PORT_UCHAR(
                    &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable);
    ((PNMI_ENABLE)(&NmiControl))->NmiDisable = 0;
    WRITE_PORT_UCHAR(
        &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, NmiControl);
#ifdef DBG
    DbgPrint("HalHandleNMI: wrote 0x%x to NmiEnable\n", NmiControl);
#endif

    return(TRUE);
}
Exemplo n.º 15
0
VOID
DigiDPCService( IN PKDPC Dpc,
                IN PVOID DeferredContext,
                IN PVOID SystemContext1,
                IN PVOID SystemContext2 )
{
   extern BOOLEAN DigiDriverInitialized; // from init.c
   PDIGI_CONTROLLER_EXTENSION ControllerExt = DeferredContext;

   DigiDump( DIGIDPCFLOW, ("DigiBoard: Entering DigiDPCService\n") );

   // Ensure the controller is intialized.
   if( DigiDriverInitialized  // We can't get here if we're not initialized. --SWA
   &&  ControllerExt->ControllerState == DIGI_DEVICE_STATE_INITIALIZED )
   {
      USHORT DownloadRequest, FepStat;
      USHORT Ein, Eout;

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

      FepStat =
         READ_REGISTER_USHORT( (PUSHORT)((PUCHAR)ControllerExt->VirtualAddress+
                                          FEP_FEPSTAT) );
      DownloadRequest =
         READ_REGISTER_USHORT( (PUSHORT)((PUCHAR)ControllerExt->VirtualAddress+
                                          FEP_DLREQ) );
      Ein =
         READ_REGISTER_USHORT( (PUSHORT)((PUCHAR)ControllerExt->VirtualAddress+
                                          FEP_EIN) );
      Eout =
         READ_REGISTER_USHORT( (PUSHORT)((PUCHAR)ControllerExt->VirtualAddress+
                                          FEP_EOUT) );

      DisableWindow( ControllerExt );

      if (FepStat!=FEP_FEPSTAT_OK)
      {
         LARGE_INTEGER CurrentSystemTime;

         KeQuerySystemTime( &CurrentSystemTime );
         InterlockedIncrement(&ControllerExt->WindowFailureCount);

         DigiDump( DIGIERRORS, ("DigiBoard: Memory Window Failure (%d)\n", ControllerExt->WindowFailureCount));

         if (CurrentSystemTime.HighPart!=ControllerExt->LastErrorLogTime.HighPart)
         {
            PHYSICAL_ADDRESS Signature;

            Signature.LowPart = 0x5a5a5a5a;
            ControllerExt->LastErrorLogTime = CurrentSystemTime;
            DigiLogError( ControllerExt->DriverObject,
                          NULL,
                          Diagnose(ControllerExt),
                          Signature,
                          0,
                          0,
                          (UCHAR)ControllerExt->WindowFailureCount,
                          __LINE__,
                          STATUS_SUCCESS,
                          SERIAL_MEMORY_WINDOW_FAILURE,
                          ControllerExt->ControllerName.Length+1,
                          ControllerExt->ControllerName.Buffer,
                          0,
                          NULL );
         }
      }
      else if( DownloadRequest ) // Look and see if there is a download request
      {
         // The Controller is requesting a concentrator download.

         XXDownload( ControllerExt );

         //
         // We don't service any ports until all concentrator
         // requests have been satisfied.
         //
      }
      else if( Ein != Eout )
      {
         //
         // Architecture ensures we have exclusive access to events on the controller.
         // (We reschedule ourselves to run, so two instances cannot coexist.)
         //
         DigiServiceEvent( ControllerExt, Ein, Eout );
      }

   }

   // Reset our timer.
   KeSetTimer( &ControllerExt->PollTimer,
               ControllerExt->PollTimerLength,
               &ControllerExt->PollDpc );

   DigiDump( DIGIDPCFLOW, ("DigiBoard: Exiting DigiDPCService\n") );

}  // DigiDPCService
Exemplo n.º 16
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
Exemplo n.º 17
0
NDIS_STATUS
CardIdentify(
    IN PHTDSU_ADAPTER       Adapter
    )

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Functional Description:

    This routine will attempt to verify that the controller is located in
    memory where the driver has been configured to expect it.

Parameters:

    Adapter _ A pointer ot our adapter information structure.

Return Values:

    NDIS_STATUS_SUCCESS
    NDIS_STATUS_ADAPTER_NOT_FOUND

---------------------------------------------------------------------------*/

{
    DBG_FUNC("CardIdentify")

    NDIS_STATUS Status;

    /*
    // These values are read from the adapter to make sure this driver will
    // work with the firmware on the adapter.
    */
    USHORT CoProcessorId;
    USHORT CoProcessorVersion;
    USHORT DsuId;
    USHORT DsuVersion;

    DBG_ENTER(Adapter);

    /*
    // Read the configuration values from the card.
    */
    CoProcessorId      = READ_REGISTER_USHORT(&Adapter->AdapterRam->CoProcessorId);
    CoProcessorVersion = READ_REGISTER_USHORT(&Adapter->AdapterRam->CoProcessorVersion);
    DsuId              = READ_REGISTER_USHORT(&Adapter->AdapterRam->DsuId);
    DsuVersion         = READ_REGISTER_USHORT(&Adapter->AdapterRam->DsuVersion);

    /*
    // Make sure these values are what we expect.
    */
    if ((CoProcessorId      == HTDSU_COPROCESSOR_ID) &&
        (CoProcessorVersion >= HTDSU_COPROCESSOR_VERSION) &&
        ((DsuId & 0x00FF)   == HTDSU_DSU_ID) &&
        (DsuVersion         >= HTDSU_DSU_VERSION))
    {
        /*
        // Record the number of lines on this adapter.
        */
        Adapter->NumLineDevs = HTDSU_NUM_LINKS;
        if ((DsuId & 0xFF00) == 0)
        {
            --Adapter->NumLineDevs;
        }
        DBG_NOTICE(Adapter,("NumLineDevs=%d\n",Adapter->NumLineDevs));

        Status = NDIS_STATUS_SUCCESS;
    }
    else
    {
        DBG_ERROR(Adapter,("Adapter not found or invalid firmware:\n"
                  "CoProcessorId      = %Xh\n"
                  "CoProcessorVersion = %Xh\n"
                  "DsuId              = %Xh\n"
                  "DsuVersion         = %Xh\n",
                  CoProcessorId,
                  CoProcessorVersion,
                  DsuId,
                  DsuVersion
                  ));

        Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
        /*
        // Log error message and return.
        */
        NdisWriteErrorLogEntry(
                Adapter->MiniportAdapterHandle,
                NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
                7,
                CoProcessorId,
                CoProcessorVersion,
                DsuId,
                DsuVersion,
                Status,
                __FILEID__,
                __LINE__
                );
    }

    DBG_LEAVE(Adapter);

    return (Status);
}
Exemplo n.º 18
0
VOID
CardPrepareTransmit(
    IN PHTDSU_ADAPTER       Adapter,
    IN USHORT               CardLine,    /* HTDSU_CMD_LINE1 or HTDSU_CMD_LINE2 */
    IN USHORT               BytesToSend
    )

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Functional Description:

    This routine will write the packet header information into the
    transmit buffer.  This assumes that the controller has notified the
    driver that the transmit buffer is empty.

Parameters:

    Adapter _ A pointer ot our adapter information structure.

    CardLine _ Specifies which line to use for the transmit (HTDSU_LINEx_ID).

    BytesToSend _ Number of bytes to transmit.

Return Values:

    None

---------------------------------------------------------------------------*/

{
    DBG_FUNC("CardPrepareTransmit")

    DBG_ENTER(Adapter);

    ASSERT((CardLine==HTDSU_CMD_LINE1) || (CardLine==HTDSU_CMD_LINE2));
    ASSERT(READ_REGISTER_USHORT(&Adapter->AdapterRam->TxDataEmpty));
    ASSERT(BytesToSend > 0);

    /*
    // Tell the adapter how many bytes are to be sent, and which line to use.
    */
    WRITE_REGISTER_USHORT(
            &Adapter->AdapterRam->TxBuffer.Address,
            (USHORT) (CardLine - HTDSU_CMD_LINE1)
            );
    WRITE_REGISTER_USHORT(
            &Adapter->AdapterRam->TxBuffer.Length,
            BytesToSend
            );

    /*
    // Mark the end of packet and end of packet list.
    */
    WRITE_REGISTER_USHORT(
            &Adapter->AdapterRam->TxBuffer.Data[(BytesToSend+1)/sizeof(USHORT)],
            HTDSU_DATA_TERMINATOR
            );
    WRITE_REGISTER_USHORT(
            &Adapter->AdapterRam->TxBuffer.Data[(BytesToSend+3)/sizeof(USHORT)],
            HTDSU_DATA_TERMINATOR
            );

    DBG_LEAVE(Adapter);
}
Exemplo n.º 19
0
VOID
KdpReadIoSpaceExtended (
    IN PDBGKD_MANIPULATE_STATE64 m,
    IN PSTRING AdditionalData,
    IN PCONTEXT Context
    )

/*++

Routine Description:

    This function is called in response of a read io space extended state
    manipulation message.  Its function is to read system io
    locations.

Arguments:

    m - Supplies the state manipulation message.

    AdditionalData - Supplies any additional data for the message.

    Context - Supplies the current context.

Return Value:

    None.

--*/

{
    PDBGKD_READ_WRITE_IO_EXTENDED64 a = &m->u.ReadWriteIoExtended;
    ULONG Length;
    STRING MessageHeader;
    PUCHAR b;
    PUSHORT s;
    PULONG l;
    ULONG BusNumber;
    ULONG AddressSpace;
    ULONG SavedAddressSpace;
    PHYSICAL_ADDRESS IoAddress;
    ULONG DataSize;
    PHYSICAL_ADDRESS TranslatedAddress;
    INTERFACE_TYPE InterfaceType;

    MessageHeader.Length = sizeof(*m);
    MessageHeader.Buffer = (PCHAR)m;

    ASSERT(AdditionalData->Length == 0);

    m->ReturnStatus = STATUS_SUCCESS;

    InterfaceType = a->InterfaceType;
    BusNumber = a->BusNumber;
    AddressSpace = SavedAddressSpace = a->AddressSpace;
    IoAddress.QuadPart = (ULONG_PTR)a->IoAddress;
    DataSize = a->DataSize;

    //
    // Zero the return data value.
    //

    a->DataValue = 0;

    //
    // Translate the bus address to the physical system address
    // or QVA.
    //

    if( !HalTranslateBusAddress( InterfaceType,
                                 BusNumber,
                                 IoAddress,
                                 &AddressSpace,
                                 &TranslatedAddress ) ){
        m->ReturnStatus = STATUS_INVALID_PARAMETER;
        goto SendReadIoSpaceExtendedResponse;
    }

    //
    // N.B. - for the moment we will only support QVAs ie. when AddressSpace
    //        is one.  It may be in later systems that we will have to
    //        check the address space, map it, perform the virtual read
    //        unmap, and then return the data - only we will have to be
    //        careful about what Irql we are to make sure the memory mgmt
    //        stuff will all work
    //

    if( !AddressSpace ){
        m->ReturnStatus = STATUS_INVALID_PARAMETER;
        goto SendReadIoSpaceExtendedResponse;
    }

    //
    // Do the IO space read using the appropriate HAL routines based upon
    // the original address space and the data size requested.
    //

    if( !SavedAddressSpace ){

        //
        // Memory (buffer) space on the bus
        //

        switch( DataSize ){

        case 1:
            a->DataValue = READ_REGISTER_UCHAR( (PUCHAR)(ULONG_PTR) TranslatedAddress.QuadPart );
            break;

        case 2:
            a->DataValue = READ_REGISTER_USHORT((PUSHORT)(ULONG_PTR) TranslatedAddress.QuadPart );
            break;

        case 4:
            a->DataValue = READ_REGISTER_ULONG((PULONG)(ULONG_PTR) TranslatedAddress.QuadPart );
            break;

        default:
            m->ReturnStatus = STATUS_INVALID_PARAMETER;
        }

    } else {

        //
        // I/O space on the bus
        //

        switch( DataSize ){

        case 1:
            a->DataValue = READ_PORT_UCHAR( (PUCHAR)(ULONG_PTR) TranslatedAddress.QuadPart );
            break;

        case 2:
            a->DataValue = READ_PORT_USHORT( (PUSHORT)(ULONG_PTR) TranslatedAddress.QuadPart );
            break;

        case 4:
            a->DataValue = READ_PORT_ULONG( (PULONG)(ULONG_PTR) TranslatedAddress.QuadPart );
            break;

        default:
            m->ReturnStatus = STATUS_INVALID_PARAMETER;
        }
    }



SendReadIoSpaceExtendedResponse:

    KdpSendPacket(
        PACKET_TYPE_KD_STATE_MANIPULATE,
        &MessageHeader,
        NULL
        );
}
Exemplo n.º 20
0
VOID
CardDialNumber(
    IN PHTDSU_ADAPTER       Adapter,
    IN USHORT               CardLine,    /* HTDSU_CMD_LINE1 or HTDSU_CMD_LINE2 */
    IN PUCHAR               DialString,
    IN ULONG                DialStringLength
    )

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Functional Description:

    Place a dial string on the adapter and start the dialing sequence.

Parameters:

    Adapter _ A pointer ot our adapter information structure.

    CardLine _ Specifies which line to use for the transmit (HTDSU_LINEx_ID).

    DialString _ A pointer to an ASCII null-terminated string of digits.

    DialStringLength _ Number of bytes in dial string.

Return Values:

    None

---------------------------------------------------------------------------*/

{
    DBG_FUNC("CardDialNumber")

    UINT    Index;
    UINT    NumDigits;    

    PUSHORT DialRam;

    DBG_ENTER(Adapter);

    ASSERT(READ_REGISTER_USHORT(&Adapter->AdapterRam->TxDataEmpty));
    ASSERT(READ_REGISTER_USHORT(&Adapter->AdapterRam->Command) == HTDSU_CMD_NOP);

    /*
    // Copy the digits to be dialed onto the adapter.
    // The adapter interprets phone numbers as high byte is valid digit,
    // low byte is ignored, the last digit gets bit 15 set.
    */
    DialRam = (PUSHORT) &Adapter->AdapterRam->TxBuffer;

    for (NumDigits = Index = 0; Index < DialStringLength && *DialString; Index++)
    {
        if ((*DialString >= '0') && (*DialString <= '9'))
        {
            WRITE_REGISTER_USHORT(
                    DialRam,
                    (USHORT) ((*DialString - '0') << 8)
                    );
            DialRam++;

            /*
            // Make sure dial string is within the limit of the adapter.
            */
            if (++NumDigits >= HTDSU_MAX_DIALING_DIGITS)
            {
                break;
            }
        }
        DialString++;
    }

    /*
    // Set the MSB in the last digit.
    */
    DialRam--;
    WRITE_REGISTER_USHORT(
            DialRam,
            (USHORT) (READ_REGISTER_USHORT(DialRam) | 0x8000)
            );

    /*
    // Initiate the dial sequence.
    */
    CardDoCommand(Adapter, CardLine, HTDSU_CMD_DIAL);

    DBG_LEAVE(Adapter);
}
Exemplo n.º 21
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