windows-nt/Source/XPSP1/NT/base/busdrv/pccard/pcmcibus/ioctl.c
2020-09-26 16:20:57 +08:00

309 lines
8.8 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1997-2000 Microsoft Corporation
Module Name:
ioctl.c
Abstract:
This module handles device ioctl's to the pcmcia driver.
Authors:
Ravisankar Pudipeddi (ravisp) Oct 15 1996
Neil Sandlin (neilsa) 1-Jun-1999
Environment:
Kernel mode
Revision History :
--*/
#include "pch.h"
NTSTATUS
PcmciaDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
IOCTL device routine
Arguments:
DeviceObject - Pointer to the device object.
Irp - Pointer to the IRP
Return Value:
Status
--*/
{
PFDO_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
PDEVICE_OBJECT pdo;
PPDO_EXTENSION pdoExtension;
PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS status = STATUS_SUCCESS;
ULONG index;
PSOCKET socket;
USHORT socketNum;
PUCHAR buffer;
ULONG bufferSize;
DebugPrint((PCMCIA_DEBUG_IOCTL, "PcmciaDeviceControl: Entered\n"));
//
// Every request requires an input buffer.
//
if (!Irp->AssociatedIrp.SystemBuffer ||
(currentIrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(TUPLE_REQUEST))) {
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INVALID_PARAMETER;
}
socketNum = ((PTUPLE_REQUEST)Irp->AssociatedIrp.SystemBuffer)->Socket;
//
// Find the socket pointer for the requested offset.
//
socket = deviceExtension->SocketList;
index = 0;
while (socket) {
if (index == socketNum) {
break;
}
socket = socket->NextSocket;
index++;
}
if (socket == NULL) {
status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
pdo = socket->PdoList;
if (pdo == NULL) {
status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
pdoExtension = pdo->DeviceExtension;
switch (currentIrpStack->Parameters.DeviceIoControl.IoControlCode) {
case IOCTL_GET_TUPLE_DATA: {
DebugPrint((PCMCIA_DEBUG_IOCTL, "Get Tuple Data\n"));
try {
ULONG bufLen = currentIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
//
// Zero the target buffer
//
RtlZeroMemory(Irp->AssociatedIrp.SystemBuffer, bufLen);
Irp->IoStatus.Information = (*(socket->SocketFnPtr->PCBReadCardMemory))(pdoExtension,
PCCARD_ATTRIBUTE_MEMORY,
0,
Irp->AssociatedIrp.SystemBuffer,
bufLen);
}except(EXCEPTION_EXECUTE_HANDLER) {
status = GetExceptionCode();
}
break;
}
case IOCTL_SOCKET_INFORMATION: {
PPCMCIA_SOCKET_INFORMATION infoRequest;
DebugPrint((PCMCIA_DEBUG_IOCTL, "socket info\n"));
infoRequest = (PPCMCIA_SOCKET_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
if (currentIrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(PCMCIA_SOCKET_INFORMATION)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
//
// Insure caller data is zero - maintain value for socket.
//
index = (ULONG) infoRequest->Socket;
RtlZeroMemory(infoRequest, sizeof(PCMCIA_SOCKET_INFORMATION));
infoRequest->Socket = (USHORT) index;
//
// Only if there is a card in the socket does this proceed.
//
PCMCIA_ACQUIRE_DEVICE_LOCK(socket->DeviceExtension);
infoRequest->CardInSocket =
(*(socket->SocketFnPtr->PCBDetectCardInSocket))(socket);
infoRequest->CardEnabled = (UCHAR) IsSocketFlagSet(pdoExtension->Socket, SOCKET_CARD_CONFIGURED);
PCMCIA_RELEASE_DEVICE_LOCK(socket->DeviceExtension);
if (infoRequest->CardInSocket) {
PSOCKET_DATA socketData = pdoExtension->SocketData;
//
// For now returned the cached data.
//
if (socketData) {
RtlMoveMemory(&infoRequest->Manufacturer[0], &socketData->Mfg[0], MANUFACTURER_NAME_LENGTH);
RtlMoveMemory(&infoRequest->Identifier[0], &socketData->Ident[0], DEVICE_IDENTIFIER_LENGTH);
infoRequest->TupleCrc = socketData->CisCrc;
infoRequest->DeviceFunctionId = socketData->DeviceType;
}
}
infoRequest->ControllerType = deviceExtension->ControllerType;
Irp->IoStatus.Information = sizeof(PCMCIA_SOCKET_INFORMATION);
break;
}
#if 0
case IOCTL_PCMCIA_TEST: {
PPCMCIA_TEST_INFORMATION testRequest;
PDO_EXTENSION TestPdoExtension = {0};
UCHAR attributeBuffer[] = {1, 2, 0, 0xff, 3, 0, 0xff, 0xff};
UCHAR indirectBuffer[] = {0x13, 3, 0x43, 0x49, 0x53, 0x15, 0x2d, 5};
ULONG index;
DebugPrint((PCMCIA_DEBUG_IOCTL, "driver test\n"));
//
// TEST CODE
// Check the CIS of the Margi DVD-to-go card
// This card has the CIS in attribute indirect memory, and was having problems
// on ToPIC controllers.
//
testRequest = (PPCMCIA_TEST_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
if (currentIrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(PCMCIA_TEST_INFORMATION)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
//
// Insure caller data is zero - maintain value for socket.
//
index = (ULONG) testRequest->Socket;
RtlZeroMemory(testRequest, sizeof(PCMCIA_TEST_INFORMATION));
testRequest->Socket = (USHORT) index;
if (!(*(socket->SocketFnPtr->PCBDetectCardInSocket))(socket)) {
DebugPrint((PCMCIA_DEBUG_FAIL, "driver test: abort because no card\n"));
status = STATUS_NOT_FOUND;
break;
}
if (IsDeviceStarted(pdoExtension)) {
DebugPrint((PCMCIA_DEBUG_FAIL, "driver test: abort because the pdo is started\n"));
status = STATUS_INVALID_DEVICE_STATE;
break;
}
if (IsSocketFlagSet(socket, SOCKET_CARD_POWERED_UP)) {
PcmciaSetSocketPower(socket, NULL, NULL, PCMCIA_POWEROFF);
}
status = PcmciaSetSocketPower(socket, NULL, NULL, PCMCIA_POWERON);
if (!NT_SUCCESS(status)) {
DebugPrint((PCMCIA_DEBUG_FAIL, "driver test: abort because powerup failed\n"));
break;
}
TestPdoExtension.Socket = socket;
//
// Read in attribute memory
//
for (index = 0; index <= 7; index++) {
if (attributeBuffer[index] != PcmciaReadCISChar(&TestPdoExtension, PCCARD_ATTRIBUTE_MEMORY, index)) {
status = STATUS_UNSUCCESSFUL;
DebugPrint((PCMCIA_DEBUG_FAIL, "driver test: abort because attribute memory test failed\n"));
break;
}
}
if (!NT_SUCCESS(status)) {
break;
}
//
// Try Common memory
//
if (0xff != PcmciaReadCISChar(&TestPdoExtension, PCCARD_COMMON_MEMORY, 0)) {
status = STATUS_UNSUCCESSFUL;
DebugPrint((PCMCIA_DEBUG_FAIL, "driver test: abort because attribute memory test failed\n"));
break;
}
//
// Read in attribute memory indirect
//
for (index = 0; index <= 7; index++) {
if (indirectBuffer[index] != PcmciaReadCISChar(&TestPdoExtension, PCCARD_ATTRIBUTE_MEMORY_INDIRECT, index)) {
status = STATUS_UNSUCCESSFUL;
DebugPrint((PCMCIA_DEBUG_FAIL, "driver test: abort because attribute memory indirect test failed\n"));
break;
}
}
if (!NT_SUCCESS(status)) {
break;
}
PcmciaSetSocketPower(socket, NULL, NULL, PCMCIA_POWEROFF);
testRequest->TestData = 0x123;
Irp->IoStatus.Information = sizeof(PCMCIA_TEST_INFORMATION);
break;
}
#endif
default: {
status = STATUS_INVALID_PARAMETER;
break;
}
}
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}