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

📄 daisychain.c

📁 鼠标Windows驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
/*++

Copyright (C) Microsoft Corporation, 1993 - 1999

Module Name:

    par12843.c

Abstract:

    This is the main module for 1284.3 functionality.  These
      function enable the selection and deselection of 1284.3
      compatable devices on the parallel port.

    The devices can be selected and deselected IRQL <= DISPATCH_LEVEL 
    by calling IOCTL_INTERNAL_SELECT_DEVICE, or 'TrySelectDevice'.
    The first call is the simplest:  the IRP will be queued in the
    parallel port driver until the port is free and then it will 
    try to select the device with the given ID from the structure
    PARALLEL_1284_COMMAND.  If successful it will with a successful 
    status, otherwise it will return with an unsuccessful status.
    The class driver may cancel this IRP at any time which serves 
    as a mechanism to timeout an allocate request.

    The 'TrySelectDevice' call returns immediately from the port
    driver with a TRUE status if the port was allocated and the
    device was able to be selected or a FALSE status if the port 
    was either busy or the device was not able to be selected.

    Once the device is selected, the port is owned by the selecting class
    driver until a 'DeselectDevice' call is made.  This deselects the
    device and also releases the port and wakes up the next caller.

Author:

    Don E. Redford  3-Mar-1998

Environment:

    Kernel mode

Revision History :


--*/

#include "pch.h"

ULONG
PptInitiate1284_3(
    IN  PVOID   Extension
    );

NTSTATUS
PptTrySelectDevice(
    IN  PVOID   Context,
    IN  PVOID   TrySelectCommand
    );

NTSTATUS
PptDeselectDevice(
    IN  PVOID   Context,
    IN  PVOID   DeselectCommand
    );

ULONG
Ppt1284_3AssignAddress(
    IN  PFDO_EXTENSION    DeviceExtension
    );

BOOLEAN
PptSend1284_3Command(
    IN  PUCHAR  CurrentPort,
    IN  UCHAR   Command
    );

BOOLEAN
PptCheckIfStl1284_3(
    IN PFDO_EXTENSION    DeviceExtension,
    IN ULONG    ulDaisyIndex,
    IN BOOLEAN  bNoStrobe
    );

BOOLEAN
PptCheckIfNon1284_3Present(
    IN PFDO_EXTENSION    Extension
    );

BOOLEAN
PptCheckIfStlProductId(
    IN PFDO_EXTENSION    Extension,
    IN ULONG   ulDaisyIndex
    );
//
// Beginning of functions
//

ULONG
PptInitiate1284_3(
    IN  PVOID   Extension
    )

/*++

Routine Description:

    This routine initializes all of the 1284.3 devices out on the
    given parallel port.  It does this by assigning 1284.3 addresses to
    each device on the port.

Arguments:

    Extensioon    - Device extension structure.

Return Value:

    None.

--*/

{
    ULONG deviceCount1 = 0;
    ULONG deviceCount2 = 0;
    ULONG loopCount    = 0;
    ULONG maxTries     = 3; // picked 3 out of thin air as a "reasonable" value

    // Send command to assign addresses and count number of 1284.3 daisy chain devices 
    // Try multiple times to make sure we get the same count
    do {

        KeStallExecutionProcessor( 5 );
        deviceCount1 = Ppt1284_3AssignAddress( Extension );

        KeStallExecutionProcessor( 5 );
        deviceCount2 = Ppt1284_3AssignAddress( Extension );

        if( deviceCount1 != deviceCount2 ) {
            DD((PCE)Extension,DDW,"PptInitiate1284_3 - count unstable\n");
            PptAssert(deviceCount1 == deviceCount2);
        }

    } while( (deviceCount1 != deviceCount2) && (++loopCount < maxTries) );

    return deviceCount2;
}

NTSTATUS
PptTrySelectDevice(
    IN  PVOID   Context,
    IN  PVOID   TrySelectCommand
    )
/*++

Routine Description:

    This routine first tries to allocate the port.  If successful
      it will then try to select  the device with the ID given.

Arguments:

    Extension   -   Driver extension.
    Device      -   1284.3 Device Id.
    Command     -   Command to know whether to allocate the port

Return Value:

    TRUE            -  Able to allocate the port and select the device
    FALSE           -  1: Invalid ID    2: Not able to allocate port    3: Not able to select device

--*/
{
    NTSTATUS                    Status = STATUS_SUCCESS;
    PFDO_EXTENSION           Extension = Context;
    PPARALLEL_1284_COMMAND      Command = TrySelectCommand;
    BOOLEAN                     success = FALSE;
    SYNCHRONIZED_COUNT_CONTEXT  SyncContext;
    KIRQL                       CancelIrql;
    UCHAR                       i, DeviceID;

    if( ( Command->CommandFlags & PAR_LEGACY_ZIP_DRIVE ) ||
        ( Command->ID == DOT3_LEGACY_ZIP_ID )) {
        Status = PptTrySelectLegacyZip(Context, TrySelectCommand);
        DD((PCE)Extension,DDT,"PptTrySelectDevice - LegacyZip - status=%x\n",Status);
        return Status;
    }

    // get device ID to select
    DeviceID = Command->ID;
            
    // validate parameters - we will accept:
    //   - a Dot3 device with a valid DeviceID
    //   - an End-of-Chain device indicated by the PAR_END_OF_CHAIN_DEVICE flag, or
    //   - an End-of-Chain device indicated by a DeviceID value one past the last Dot3 device

    if ( !(Command->CommandFlags & PAR_END_OF_CHAIN_DEVICE) && DeviceID > Extension->PnpInfo.Ieee1284_3DeviceCount ) {
                
        // Requested device is not flagged as End-of-Chain device and DeviceID
        //   is more than one past the end of the Dot3 Devices, so FAIL the IRP
        DD((PCE)Extension,DDE,"PptTrySelectDevice - FAIL - invalid DeviceID parameter\n",DeviceID);
        PptAssertMsg("PptTrySelectDevice - FAIL - invalid DeviceID parameter",FALSE);
        Status = STATUS_INVALID_PARAMETER;
                
    } else {
                
        //
        // Request appears valid
        //

        // test to see if we need to grab port
        if( Command->CommandFlags & PAR_HAVE_PORT_KEEP_PORT ) {

            //
            // requester has already acquired port, just do a SELECT
            //
            if ( !(Command->CommandFlags & PAR_END_OF_CHAIN_DEVICE) &&
                    DeviceID < Extension->PnpInfo.Ieee1284_3DeviceCount ) {

                // SELECT the device
                for ( i = 0; i < PptDot3Retries && !success; i++ ) {
                    // Send command to to select device in compatability mode
                    success = PptSend1284_3Command( Extension->PortInfo.Controller, (UCHAR)(CPP_SELECT | DeviceID) );
                    // Stall a little in case we have to retry
                    KeStallExecutionProcessor( 5 );
                }                

                if ( success ) {
                    DD((PCE)Extension,DDT,"PptTrySelectDevice - had port - SUCCESS\n");
                    Status = STATUS_SUCCESS;
                } else {
                    DD((PCE)Extension,DDW,"PptTrySelectDevice - FAIL\n");
                    Status = STATUS_UNSUCCESSFUL;
                }
            } else {
                // End-of-Chain device, no SELECT required, SUCCEED the request
                DD((PCE)Extension,DDT,"PptTrySelectDevice - EOC\n");
                Status = STATUS_SUCCESS;
            }

        } else {

            // Don't have the port

            //
            // Try to acquire port and select device
            //
            IoAcquireCancelSpinLock(&CancelIrql);
                
            SyncContext.Count = &Extension->WorkQueueCount;
                    
            if (Extension->InterruptRefCount) {
                KeSynchronizeExecution(Extension->InterruptObject, PptSynchronizedIncrement, &SyncContext);
            } else {
                PptSynchronizedIncrement(&SyncContext);
            }
                    
            if (SyncContext.NewCount) {
                // Port is busy, queue request
                DD((PCE)Extension,DDT,"PptTrySelectDevice - Port Busy - Request Queued\n");
                IoReleaseCancelSpinLock(CancelIrql);
                Status = STATUS_PENDING;

            } else {

                IoReleaseCancelSpinLock(CancelIrql);
                        
                // Port is acquired
                DD((PCE)Extension,DDT,"PptTrySelectDevice - Port Acquired\n");

                Extension->WmiPortAllocFreeCounts.PortAllocates++;

                if ( !(Command->CommandFlags & PAR_END_OF_CHAIN_DEVICE) && DeviceID < Extension->PnpInfo.Ieee1284_3DeviceCount ) {
                            
                    // SELECT the device
                    for ( i = 0; i < PptDot3Retries && !success; i++ ) {
                        // Send command to to select device in compatability mode
                        success = PptSend1284_3Command( Extension->PortInfo.Controller, (UCHAR)(CPP_SELECT | DeviceID) );
                        // Stall a little in case we have to retry
                        KeStallExecutionProcessor( 5 );
                    }                

                    if ( success ) {
                        DD((PCE)Extension,DDT,"PptTrySelectDevice - SUCCESS\n");
                        Status = STATUS_SUCCESS;
                    } else {
                        DD((PCE)Extension,DDW,"PptTrySelectDevice - FAILED\n");

                        // RMT - 000831 - do we still have the port locked!?! - did we hang the port?

                        Status = STATUS_UNSUCCESSFUL;
                    }

                } else {
                    // End-of-Chain device, no SELECT required, SUCCEED the request
                    DD((PCE)Extension,DDT,"PptTrySelectDevice - EOC2\n");
                    Status = STATUS_SUCCESS;
                }

            }  // endif - test for port busy
                    
        } // endif - test if already have port

    } // endif - test for valid parameters

    return Status;
}

NTSTATUS
PptDeselectDevice(
    IN  PVOID   Context,
    IN  PVOID   DeselectCommand
    )
    
/*++

Routine Description:

    This routine deselects the current device and then frees the port

Arguments:


Return Value:

    TRUE            -  Able to deselect the device and free the port
    FALSE           -  1: Invalid ID    2: Not able to deselect the drive

--*/

{
    NTSTATUS                Status = STATUS_SUCCESS;
    PFDO_EXTENSION       fdx = Context;
    PPARALLEL_1284_COMMAND  Command = DeselectCommand;
    BOOLEAN                 success = FALSE;
    UCHAR                   i, DeviceID;

    if( ( Command->CommandFlags & PAR_LEGACY_ZIP_DRIVE ) ||
        ( Command->ID == DOT3_LEGACY_ZIP_ID ) ) {
        return PptDeselectLegacyZip( Context, DeselectCommand );
    }

    // get device ID to deselect
    DeviceID = Command->ID;

    // validate ID
    if ( !(Command->CommandFlags & PAR_END_OF_CHAIN_DEVICE) && DeviceID > fdx->PnpInfo.Ieee1284_3DeviceCount ) {

        // not End-of-Chain device and Dot3 DeviceID is invalid
        DD((PCE)fdx,DDE,"PptDeselectDevice - ID=%d - FAIL - invalid parameter\n",DeviceID);
        Status = STATUS_INVALID_PARAMETER;
                
    } else {
                
        // Check for End-of-Chain device
        if ( !(Command->CommandFlags & PAR_END_OF_CHAIN_DEVICE) &&
                DeviceID < fdx->PnpInfo.Ieee1284_3DeviceCount ) {
                    
            // first deselect the device 
            for ( i = 0; i < PptDot3Retries && !success; i++ ) {
                success = PptSend1284_3Command( fdx->PortInfo.Controller, (UCHAR)CPP_DESELECT );
                // Stall a little in case we have to retry
                KeStallExecutionProcessor( 5 );
            }

            if ( success ) {
                // Deselecting device was a success
                DD((PCE)fdx,DDT,"PptDeselectDevice\n");

                // check if requester wants to keep port or free port
                if( !(Command->CommandFlags & PAR_HAVE_PORT_KEEP_PORT) ) {
                    PptFreePort( fdx );
                }
                Status = STATUS_SUCCESS;
                        
            } else {
                // Unable to deselect device, something went very wrong,
                //   port is now in an unknown/blocked state
                DD((PCE)fdx,DDE,"PptDeselectDevice - ID=%d - FAIL\n",DeviceID);
                PptAssertMsg("PptDeselectDevice - FAIL - port in unknown state",FALSE);
                Status = STATUS_UNSUCCESSFUL;
            }
                    
        } else {

            // this is End-of-Chain device so no deselect neccessary
            DD((PCE)fdx,DDT,"PptDeselectDevice - End-of-Chain - SUCCESS\n",DeviceID);

            // check if requester wants to keep port or free port
            if( !(Command->CommandFlags & PAR_HAVE_PORT_KEEP_PORT) ) {
                PptFreePort( fdx );
            }
            Status = STATUS_SUCCESS;

        }  // endif - Check if End Of Chain

    } // endif - Validate ID

    return Status;
}


ULONG
Ppt1284_3AssignAddress(
    IN  PFDO_EXTENSION    DeviceExtension
    )

/*++

Routine Description:

    This routine initializes the 1284_3 bus.

Arguments:

    DeviceExtension    - Supplies Device Extension structure of the driver.

Return Value:

    Number of 1284.3 devices out there at the given address.

--*/

{

    //UCHAR  i, ii, value, newvalue, status;
    UCHAR  i, value, newvalue, status;
    PUCHAR CurrentPort, CurrentStatus, CurrentControl;
    ULONG  Delay = 5;
    UCHAR  number = 0;
    BOOLEAN lastdevice = FALSE;
    UCHAR   idx;

⌨️ 快捷键说明

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