|
|
/*++
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; }
|