309 lines
8.8 KiB
C
309 lines
8.8 KiB
C
|
/*++
|
|||
|
|
|||
|
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;
|
|||
|
}
|
|||
|
|