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

📄 parmode.c

📁 win2k kernel 的并口驱动程序模板
💻 C
📖 第 1 页 / 共 4 页
字号:
    Extension   - Supplies the device extension.

Return Value:

    STATUS_SUCCESS  - if it was successful.
   !STATUS_SUCCESS  - otherwise.

--*/

{

    UCHAR   ecr;
    PUCHAR  Controller;
    PUCHAR  wPortECR;
    
    Controller = Extension->PortInfo.Controller;
    
    //
    // Restore the prior mode.
    //

    // Get original ECR register
    ecr = Extension->EcrPortData;
    Extension->EcrPortData = 0;

    // some chips require to change modes only after 
    // you put it into spp mode

#if (0 == DVRH_USE_PARPORT_ECP_ADDR)
    wPortECR = Controller + ECR_OFFSET;
#else
    wPortECR = Extension->PnpInfo.EcpController + ECR_OFFSET;
#endif

    WRITE_PORT_UCHAR( wPortECR, (UCHAR)(ecr & ECR_MODE_MASK) );

    // Back to original mode
    WRITE_PORT_UCHAR( wPortECR, ecr );
    
    return STATUS_SUCCESS;

}

NTSTATUS
PptFindNatChip(
    IN  PDEVICE_EXTENSION   Extension
    )

/*++

Routine Description:

    This routine finds out if there is a National Semiconductor IO chip on
    this machine.  If it finds a National chip it then determines if this 
    instance of Parport is using this chips paralle port IO address.

Arguments:

    Extension   - Supplies the device extension.

Return Value:

    STATUS_SUCCESS       - if we were able to check for the parallel chip.
    STATUS_UNSUCCESSFUL  - if we were not able to check for the parallel chip.

Updates:
    
    Extension->
            NationalChecked
            NationalChipFound

--*/

{
    BOOLEAN             found = FALSE;              // return code, assumed value
    BOOLEAN             OkToLook = FALSE;
    BOOLEAN             Conflict;
    PUCHAR              ChipAddr[4] = { (PUCHAR)0x398, (PUCHAR)0x26e, (PUCHAR)0x15c, (PUCHAR)0x2e };  // list of valid chip addresses
    PUCHAR              AddrList[4] = { (PUCHAR)0x378, (PUCHAR)0x3bc, (PUCHAR)0x278, (PUCHAR)0x00 };  // List of valid Parallel Port addresses
    PUCHAR              PortAddr;                   // Chip Port Address
    ULONG_PTR           Port;                       // Chip Port Read Value
    UCHAR               SaveIdx;                    // Save the index register value
    UCHAR               cr;                         // config register value
    UCHAR               ii;                         // loop index
    NTSTATUS            Status;                     // Status of success
    ULONG               ResourceDescriptorCount;
    ULONG               ResourcesSize;
    PCM_RESOURCE_LIST   Resources;
    ULONG               NationalChecked   = 0;
    ULONG               NationalChipFound = 0;

    
    //
    // Quick exit if we already know the answer
    //
    if ( Extension->NationalChecked == TRUE ) {
        PptDump2(PARINITDEV, ("ParMode::PptFindNatChip: Already found NatSemi\n") );
        return STATUS_SUCCESS;
    }

    //
    // Mark extension so that we can quick exit the next time we are asked this question
    //
    Extension->NationalChecked = TRUE; 

    //
    // Check the registry - we should only need to check this once per installation
    //
    PptRegGetDeviceParameterDword(Extension->PhysicalDeviceObject, (PWSTR)L"NationalChecked", &NationalChecked);
    if( NationalChecked ) {
        //
        // We previously performed the NatSemi Check - extract result from registry
        //
        PptRegGetDeviceParameterDword(Extension->PhysicalDeviceObject, (PWSTR)L"NationalChipFound", &NationalChipFound);
        if( NationalChipFound ) {
            Extension->NationalChipFound = TRUE;
        } else {
            Extension->NationalChipFound = FALSE;
        }
        return STATUS_SUCCESS;
    }

    //
    // This is our first, and hopefully last time that we need to make this check
    //   for this installation
    //

    //
    // Allocate a block of memory for constructing a resource descriptor
    //

    // number of partial descriptors 
    ResourceDescriptorCount = sizeof(ChipAddr)/sizeof(ULONG);

    // size of resource descriptor list + space for (n-1) more partial descriptors
    //   (resource descriptor list includes one partial descriptor)
    ResourcesSize =  sizeof(CM_RESOURCE_LIST) +
        (ResourceDescriptorCount - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);

    Resources = (PCM_RESOURCE_LIST)ExAllocatePool(NonPagedPool, ResourcesSize);

    if (Resources == NULL) {
        PptDump2(PARINITDEV, ("ParMode::PptFindNatChip: No Resources Punting\n"));
        // Error out
        return(STATUS_UNSUCCESSFUL);
    }

    // zero out memory block as a precaution
    RtlZeroMemory(Resources, ResourcesSize);

    //
    // Build the Resource List
    //
    Status = PptBuildResourceList( Extension,
                                   sizeof(ChipAddr)/sizeof(ULONG),
                                   &ChipAddr[0],
                                   Resources
                                   );
    
    // Check to see if it was successful    
    if ( !NT_SUCCESS( Status ) )
    {
        PptDump2(PARINITDEV, ("ParMode::PptFindNatChip: Couldn't build Resources list. Punting\n") );
        ExFreePool( Resources );
        return ( Status );
    }

    // 
    // check to see if we can use the io addresses where
    // national chipsets are located
    //
    Status = IoReportResourceUsage( NULL,
                                    Extension->DriverObject,
                                    Resources,
                                    sizeof(Resources),
                                    Extension->DeviceObject,
                                    NULL,
                                    0,
                                    FALSE,
                                    &Conflict
                                    ); 

    // done with resource list
    ExFreePool( Resources );

    // Check to see if IoReportResourceUsage was successful    
    if ( !NT_SUCCESS( Status ) )
    {
        PptDump2(PARINITDEV, ("ParMode::PptFindNatChip: Couldn't report usage. Punting\n") );
        return ( Status );
    }

    // Check to see if it was successful    
    if ( Conflict )
    {
        PptDump2(PARINITDEV, ("ParMode::PptFindNatChip: Conflict. Punting\n"));
        return ( STATUS_UNSUCCESSFUL );
    }


    // Was successful so now we check each of the addresses that we have
    // the resources for
    //
    // the following for loop is a state machine that checks modes and
    // port addresses.
    //
    // state 0: check for Pc873 at primary port address
    // state 1: check for Pc873 at secondary port address
    // state 2: check for Pc873 at Ter port address
    // state 3: check for Pc873 at Quad port address
    
    for ( ii = 0; !found && ii < 4; ii++ ) {

        PortAddr = (PUCHAR)ChipAddr[ii];

        // After power up the index register will read back an 0xAA one time only.
        // So we'll check for that first.
        // Then it should read back a 0 or a valid register number
            
        if(( READ_PORT_UCHAR( PortAddr ) == 0x88 )
           && ( READ_PORT_UCHAR( PortAddr ) < 0x20 )) {

            OkToLook = TRUE;

        } else {

            // Or it could read back a 0 or a valid register number
            READ_PORT_UCHAR( PortAddr );        // may read back 0 here
            cr = READ_PORT_UCHAR( PortAddr );   // valid register no.
  
            // is it really valid?
            // if( cr < 0x20 ) { - dvdr
            if( cr != 0xff ) {
                // does it read back the same?
                if( READ_PORT_UCHAR( PortAddr ) == cr)
                    OkToLook = TRUE;
            }

        } // end else
            
        // take a closer look by writing to the chip
        if ( OkToLook ) {

            OkToLook = FALSE;
                    
            // setup for ID reg
            WRITE_PORT_UCHAR( PortAddr, REG_CR8 );
                            
            // read it back
            cr = READ_PORT_UCHAR( PortAddr );
                            
            // does it read back the same?
            if( cr  == REG_CR8 ) {

                // get the ID number.
                cr = (UCHAR)( READ_PORT_UCHAR( PortAddr + 1 ) & 0xf0 );
                                    
                // if the up. nib. is 1,3,5,6,7,9,A,B,C
                if( cr == PC87332 || cr == PC87334 || cr == PC87306 || cr == PC87303 || 
                   cr == PC87323 || cr == PC87336 || cr == PC87338 || cr == PC873xx ) {

                    // we found a national chip
                    found = TRUE;

                    // setup for Address reg
                    WRITE_PORT_UCHAR( PortAddr, REG_CR1 );
                    
                    // read it back
                    Port = READ_PORT_UCHAR( PortAddr + 1 ) & 0x03;
                    
                    // Check the base address
                    if ( Extension->PortInfo.Controller == (PUCHAR)AddrList[ Port ] ) {

                        //
                        // it is using the same address that Parport is using
                        // so we set the flag to not use generic ECP and EPP
                        //
                        Extension->NationalChipFound = TRUE;

                    }
                            
                }

            } // reads back ok
                            
        } // end OkToLook

        // check to see if we found it
        if ( !found ) {

            // Check for the 307/308 chips
            SaveIdx = READ_PORT_UCHAR( PortAddr );

            // Setup for SID Register
            WRITE_PORT_UCHAR( PortAddr, PC873_DEVICE_ID );
                    
            // Zero the ID register to start and because it is read only it will
            // let us know whether it is this chip
            WRITE_PORT_UCHAR( PortAddr + 1, REG_CR0 );
                    
            // get the ID number.
            cr = (UCHAR)( READ_PORT_UCHAR( PortAddr + 1 ) & 0xf8 );
                    
            if ( (cr == PC87307) || (cr == PC87308) ) {

                // we found a new national chip
                found = TRUE;

                // Set the logical device
                WRITE_PORT_UCHAR( PortAddr, PC873_LOGICAL_DEV_REG );
                WRITE_PORT_UCHAR( PortAddr+1, PC873_PP_LDN );

                // set up for the base address MSB register
                WRITE_PORT_UCHAR( PortAddr, PC873_BASE_IO_ADD_MSB );
                            
                // get the MSB of the base address
                Port = (ULONG_PTR)((READ_PORT_UCHAR( PortAddr + 1 ) << 8) & 0xff00);
                            
                // Set up for the base address LSB register
                WRITE_PORT_UCHAR( PortAddr, PC873_BASE_IO_ADD_LSB );
                            
                // Get the LSBs of the base address
                Port |= READ_PORT_UCHAR( PortAddr + 1 );
                            
                // Check the base address
                if ( Extension->PortInfo.Controller == (PUCHAR)Port ) {
                    //
                    // it is using the same address that Parport is using
                    // so we set the flag to not use generic ECP and EPP
                    //
                    Extension->NationalChipFound = TRUE;
                }

            } else {

                WRITE_PORT_UCHAR( PortAddr, SaveIdx );
            }
        }

    } // end of for ii...
    

    //
    // Check for NatSemi chip is complete - save results in registry so that we never
    //   have to make this check again for this port
    //
    {
        PDEVICE_OBJECT pdo = Extension->PhysicalDeviceObject;
        NationalChecked    = 1;
        NationalChipFound  = Extension->NationalChipFound ? 1 : 0;
        
        // we ignore status here because there is nothing we can do if the calls fail
        PptRegSetDeviceParameterDword(pdo, (PWSTR)L"NationalChecked",   &NationalChecked);
        PptRegSetDeviceParameterDword(pdo, (PWSTR)L"NationalChipFound", &NationalChipFound);
    }


    // 
    // release the io addresses where we checked for the national chipsets
    // we do this by calling IoReportResourceUsage with all NULL parameters
    //
    Status = IoReportResourceUsage( NULL,
                                    Extension->DriverObject,
                                    NULL,
                                    0,
                                    Extension->DeviceObject,
                                    NULL,
                                    0,
                                    FALSE,
                                    &Conflict
                                    ); 

    PptDump2(PARINITDEV, ("ParMode::PptFindNatChip: return isFound [%x]\n", Extension->NationalChipFound));
    return ( Status );
    
} // end of ParFindNat()

NTSTATUS
PptBuildResourceList(
    IN  PDEVICE_EXTENSION   Extension,
    IN  ULONG               Partial,
    IN  PULONG              Addresses,
    OUT PCM_RESOURCE_LIST   Resources
    )

/*++

Routine Description:

    This routine Builds a CM_RESOURCE_LIST with 1 Full Resource
    Descriptor and as many Partial resource descriptors as you want
    with the same parameters for the Full.  No Interrupts or anything
    else just IO addresses.

Arguments:

    Extension   - Supplies the device extension.
    Partial     - Number (array size) of partial descriptors in Addresses[]
    Addresses   - Pointer to an Array of addresses of the partial descriptors
    Resources   - The returned CM_RESOURCE_LIST

Return Value:

    STATUS_SUCCESS       - if the building of the list was successful.
    STATUS_UNSUCCESSFUL  - otherwise.

--*/

{

    UCHAR       i;

    //
    // Number of Full Resource descriptors
    //
    Resources->Count = 1;
    
    Resources->List[0].InterfaceType = Extension->InterfaceType;
    Resources->List[0].BusNumber = Extension->BusNumber;
    Resources->List[0].PartialResourceList.Version = 0;
    Resources->List[0].PartialResourceList.Revision = 0;
    Resources->List[0].PartialResourceList.Count = Partial;

    //
    // Going through the loop for each partial descriptor
    //
    for ( i = 0; i < Partial ; i++ ) {

        //
        // Setup port
        //
        Resources->List[0].PartialResourceList.PartialDescriptors[i].Type = CmResourceTypePort;
        Resources->List[0].PartialResourceList.PartialDescriptors[i].ShareDisposition = CmResourceShareDriverExclusive;
        Resources->List[0].PartialResourceList.PartialDescriptors[i].Flags = CM_RESOURCE_PORT_IO;
        Resources->List[0].PartialResourceList.PartialDescriptors[i].u.Port.Start.QuadPart = Addresses[i];
        Resources->List[0].PartialResourceList.PartialDescriptors[i].u.Port.Length = (ULONG)2;

    }


    return ( STATUS_SUCCESS );

}

⌨️ 快捷键说明

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