NT4/private/ntos/ndis/pcimac/io_core.c
2020-09-30 17:12:29 +02:00

323 lines
7.8 KiB
C

/*
* IO_CORE.C - core routines for IO module
*/
#include <ndis.h>
//#include <ndismini.h>
#include <ndiswan.h>
#include <mydefs.h>
#include <mytypes.h>
#include <util.h>
#include <disp.h>
#include <adapter.h>
#include <idd.h>
#include <mtl.h>
#include <cm.h>
#include <trc.h>
#include <io.h>
extern DRIVER_BLOCK Pcimac;
/* store location for prev. ioctl handler */
extern NTSTATUS (*PrevIoctl)(DEVICE_OBJECT* DeviceObject, IRP* Irp);
/* ioctl filter */
NTSTATUS
PcimacIoctl(DEVICE_OBJECT *DeviceObject, IRP *Irp)
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS ini_exec_irp(IRP* irp, IO_STACK_LOCATION* irpsp);
/* must be an ioctl, else pass this one */
if ( irpSp->MajorFunction != IRP_MJ_DEVICE_CONTROL )
{
pass:
NdisReleaseSpinLock(&Pcimac.lock);
return(PrevIoctl(DeviceObject, Irp));
}
/* must be our own private ioctl code */
if (irpSp->Parameters.DeviceIoControl.IoControlCode != IO_IOCTL_PCIMAC_EXEC )
goto pass;
/* one of our own, execute */
Irp->IoStatus.Information = 0L;
ExecIrp(Irp, irpSp);
/* complete irp */
Irp->IoStatus.Status = status;
IoSetCancelRoutine (Irp, NULL);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(status);
}
/* execute ioctl irp */
NTSTATUS
ExecIrp(IRP *irp, IO_STACK_LOCATION *irpsp)
{
UCHAR *in_buf, *out_buf;
ULONG in_len, out_len;
NTSTATUS stat;
/* establish in/out buffers */
out_len = irpsp->Parameters.DeviceIoControl.OutputBufferLength;
in_len = irpsp->Parameters.DeviceIoControl.InputBufferLength;
out_buf = irp->UserBuffer;
in_buf = irp->AssociatedIrp.SystemBuffer;
/* in/out length must be the same */
if ( in_len != out_len )
return(STATUS_UNSUCCESSFUL);
/* copy in buffer into output buffer */
NdisMoveMemory(out_buf, in_buf, out_len);
/* execute command in place */
if ( (stat = io_execute((IO_CMD*)out_buf,irp)) == IO_E_PENDING)
/* event added pend irp */
return (STATUS_PENDING);
else
/* return success */
return(STATUS_SUCCESS);
}
/* execute an io command */
INT
io_execute(IO_CMD *cmd, VOID *Irp_1)
{
IRP *Irp = (IRP*)Irp_1;
D_LOG(D_ENTRY, ("io_execute: entry, cmd: 0x%p", cmd));
/* check signature & version */
if ( cmd->sig != IO_CMD_SIG )
return(IO_E_BADSIG);
if ( (cmd->ver_major != IO_VER_MAJOR) ||
(cmd->ver_minor != IO_VER_MINOR) )
return(IO_E_BADVER);
D_LOG(D_ALWAYS, ("io_execute: opcode: 0x%x, cm: 0x%p, idd: 0x%p", \
cmd->opcode, cmd->cm, cmd->idd));
D_LOG(D_ALWAYS, ("io_execute: args: 0x%x 0x%x 0x%x 0x%x", \
cmd->arg[0], cmd->arg[1], cmd->arg[2], cmd->arg[3]));
/* clear status, assume success */
cmd->status = IO_E_SUCC;
/* branch on opcode */
switch ( cmd->opcode )
{
case IO_CMD_ENUM_ADAPTERS :
cmd->status = IoEnumAdapter(cmd);
break;
case IO_CMD_ENUM_CM:
cmd->status = IoEnumCm(cmd);
break;
case IO_CMD_ENUM_IDD :
cmd->status = IoEnumIdd(cmd);
break;
case IO_CMD_TRC_RESET :
cmd->status = trc_control(cmd->idd,
TRC_OP_RESET, (ULONG)cmd->idd);
break;
case IO_CMD_TRC_STOP :
cmd->status = trc_control(cmd->idd,
TRC_OP_STOP, (ULONG)cmd->idd);
break;
case IO_CMD_TRC_START :
cmd->status = trc_control(cmd->idd,
TRC_OP_START, (ULONG)cmd->idd);
break;
case IO_CMD_TRC_SET_FILT :
cmd->status = trc_control(cmd->idd,
TRC_OP_SET_FILTER, cmd->arg[0]);
break;
case IO_CMD_IDD_RESET_AREA :
cmd->status = idd_reset_area(cmd->idd);
break;
case IO_CMD_IDD_GET_AREA :
cmd->status = idd_get_area(cmd->idd, cmd->arg[0], NULL, NULL);
break;
case IO_CMD_IDD_GET_STAT :
cmd->status = idd_get_area_stat(cmd->idd, &cmd->val.IddStat);
break;
case IO_CMD_TRC_CREATE:
cmd->status = trc_control(cmd->idd,
TRC_OP_CREATE, cmd->arg[0]);
break;
case IO_CMD_TRC_DESTROY:
cmd->status = trc_control(cmd->idd,
TRC_OP_DESTROY, cmd->arg[0]);
break;
case IO_CMD_TRC_GET_STAT :
cmd->status = trc_get_status(idd_get_trc(cmd->idd),
&cmd->val.trc_stat);
break;
case IO_CMD_TRC_GET_ENT :
cmd->status = trc_get_entry(idd_get_trc(cmd->idd),
cmd->arg[0], &cmd->val.trc_ent);
break;
case IO_CMD_DBG_LEVEL :
SetDebugLevel(cmd);
break;
case IO_CMD_DO_IDP_CMD:
DbgPrint("DoIdpCmd: Cmd: 0x%x\n", cmd->arg[0]);
if (cmd->idd && ((IDD*)cmd->idd)->btype != IDD_BT_DATAFIREU)
{
switch (cmd->arg[0])
{
case GET_IDP_IO_VALUE:
cmd->val.IdpRaw.uc = IdpGetUByteIO(cmd->idd,
cmd->val.IdpRaw.us);
cmd->status = IO_E_SUCC;
break;
case GET_IDP_BUFFER:
IdpGetBuffer(cmd->idd,
cmd->val.IdpRaw.Bank,
cmd->val.IdpRaw.Page,
cmd->val.IdpRaw.Address,
cmd->val.IdpRaw.Length,
cmd->val.IdpRaw.Buffer);
cmd->status = IO_E_SUCC;
break;
case SET_IDP_IO_VALUE:
IdpPutUByteIO(cmd->idd,
(USHORT)cmd->val.IdpRaw.Address,
cmd->val.IdpRaw.uc);
cmd->status = IO_E_SUCC;
break;
case SET_IDP_BUFFER:
IdpPutBuffer(cmd->idd,
cmd->val.IdpRaw.Bank,
cmd->val.IdpRaw.Page,
cmd->val.IdpRaw.Address,
cmd->val.IdpRaw.Length,
cmd->val.IdpRaw.Buffer);
cmd->status = IO_E_SUCC;
break;
default:
cmd->status = IO_E_BADCMD;
break;
}
}
else
cmd->status = IO_E_BADIDD;
break;
case IO_CMD_DO_ADP_CMD:
if (cmd->idd && ((IDD*)cmd->idd)->btype == IDD_BT_DATAFIREU)
{
switch (cmd->arg[0])
{
case GET_ADP_UCHAR:
cmd->val.AdpRaw.uc = AdpGetUByte(cmd->idd,
cmd->val.AdpRaw.Address);
cmd->status = IO_E_SUCC;
break;
case GET_ADP_USHORT:
cmd->val.AdpRaw.us = AdpGetUShort(cmd->idd,
cmd->val.AdpRaw.Address);
cmd->status = IO_E_SUCC;
break;
case GET_ADP_ULONG:
cmd->val.AdpRaw.ul = AdpGetULong(cmd->idd,
cmd->val.AdpRaw.Address);
cmd->status = IO_E_SUCC;
break;
case GET_ADP_BUFFER:
AdpGetBuffer(cmd->idd,
cmd->val.AdpRaw.Buffer,
cmd->val.AdpRaw.Address,
cmd->val.AdpRaw.Length
);
cmd->status = IO_E_SUCC;
break;
case SET_ADP_UCHAR:
AdpPutUByte(cmd->idd,
cmd->val.AdpRaw.Address,
cmd->val.AdpRaw.uc);
cmd->status = IO_E_SUCC;
break;
case SET_ADP_USHORT:
AdpPutUShort(cmd->idd,
cmd->val.AdpRaw.Address,
cmd->val.AdpRaw.us);
cmd->status = IO_E_SUCC;
break;
case SET_ADP_ULONG:
AdpPutULong(cmd->idd,
cmd->val.AdpRaw.Address,
cmd->val.AdpRaw.ul);
cmd->status = IO_E_SUCC;
break;
case SET_ADP_BUFFER:
AdpPutBuffer(cmd->idd,
cmd->val.AdpRaw.Address,
cmd->val.AdpRaw.Buffer,
cmd->val.AdpRaw.Length);
cmd->status = IO_E_SUCC;
break;
default:
cmd->status = IO_E_BADCMD;
break;
}
}
else
cmd->status = IO_E_BADIDD;
break;
default :
cmd->status = IO_E_BADCMD;
break;
}
/* return status code */
return((INT)cmd->status);
}