mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
672 lines
13 KiB
672 lines
13 KiB
/*
|
|
* IDD_IO.C - do inp/outp ops for idd modules
|
|
*/
|
|
|
|
#include <ndis.h>
|
|
#include <mytypes.h>
|
|
#include <mydefs.h>
|
|
#include <disp.h>
|
|
#include <util.h>
|
|
#include <opcodes.h>
|
|
#include <idd.h>
|
|
#include <res.h>
|
|
|
|
typedef union
|
|
{
|
|
UCHAR uc[4];
|
|
ULONG ul;
|
|
}ULONG_UNION;
|
|
|
|
typedef union
|
|
{
|
|
UCHAR uc[2];
|
|
USHORT us;
|
|
}USHORT_UNION;
|
|
|
|
/* output to a port */
|
|
VOID
|
|
IdpOutp(
|
|
IDD *idd,
|
|
USHORT port,
|
|
UCHAR val)
|
|
{
|
|
NdisRawWritePortUchar((ULONG)idd->vhw.vbase_io + port, val);
|
|
}
|
|
|
|
/* input from a port */
|
|
UCHAR
|
|
IdpInp(
|
|
IDD *idd,
|
|
USHORT port)
|
|
{
|
|
UCHAR val;
|
|
|
|
NdisRawReadPortUchar((ULONG)idd->vhw.vbase_io + port, &val);
|
|
|
|
return(val);
|
|
}
|
|
|
|
/* output to a port */
|
|
VOID
|
|
AdpOutp(
|
|
IDD *idd,
|
|
USHORT port,
|
|
UCHAR val
|
|
)
|
|
{
|
|
//
|
|
// Determine if this is a multi-channel BRI adapter. If so, then
|
|
// we need to select the correct ADP to reference.
|
|
//
|
|
// IMPORTANT NOTE: I can get away with this because we process IDD's
|
|
// on a per adapter basis. If this ever changes,
|
|
// then it may be necessary to change what is done
|
|
// here.
|
|
//
|
|
switch( idd->btype )
|
|
{
|
|
case IDD_BT_DATAFIRE4ST:
|
|
//
|
|
// select the correct BRI channel to access.
|
|
//
|
|
NdisRawWritePortUchar( (ULONG)idd->vhw.vbase_io + ADP_REG_ADAPTER_CTRL,
|
|
idd->bline );
|
|
break;
|
|
}
|
|
|
|
NdisRawWritePortUchar((ULONG)idd->vhw.vbase_io + port, val);
|
|
} // end AdpOutp
|
|
|
|
/* input from a port */
|
|
UCHAR
|
|
AdpInp(
|
|
IDD *idd,
|
|
USHORT port
|
|
)
|
|
{
|
|
UCHAR val;
|
|
|
|
//
|
|
// Determine if this is a multi-channel BRI adapter. If so, then
|
|
// we need to select the correct ADP to reference.
|
|
//
|
|
// IMPORTANT NOTE: I can get away with this because we process IDD's
|
|
// on a per adapter basis. If this ever changes,
|
|
// then it may be necessary to change what is done
|
|
// here.
|
|
//
|
|
switch( idd->btype )
|
|
{
|
|
case IDD_BT_DATAFIRE4ST:
|
|
//
|
|
// select the correct BRI channel to access.
|
|
//
|
|
NdisRawWritePortUchar( (ULONG)idd->vhw.vbase_io + ADP_REG_ADAPTER_CTRL,
|
|
idd->bline );
|
|
break;
|
|
}
|
|
|
|
NdisRawReadPortUchar((ULONG)idd->vhw.vbase_io + port, &val);
|
|
|
|
return(val);
|
|
} // end AdpInp
|
|
|
|
VOID AdpWriteControlBit( IDD *idd,
|
|
UCHAR Bit,
|
|
UCHAR Value )
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sets bits indicated to specified values.
|
|
|
|
Arguments:
|
|
|
|
Bit - BitMask of which bits are to be set.
|
|
|
|
Value - BitMask to be applied to for Bit.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
UCHAR OldData, NewData;
|
|
|
|
// Read old value.
|
|
OldData = idd->InFromPort( idd, ADP_REG_CTRL );
|
|
|
|
// Set new value
|
|
NewData = (OldData & Bit) | Value;
|
|
|
|
// Data &= ~Bit;
|
|
// Data |= (Value ? Bit : 0);
|
|
|
|
idd->OutToPort(idd, ADP_REG_CTRL, NewData);
|
|
}
|
|
|
|
UCHAR
|
|
AdpReadReceiveStatus(
|
|
IDD *idd
|
|
)
|
|
{
|
|
return(AdpGetUByte(idd, ADP_STS_WINDOW));
|
|
}
|
|
|
|
//
|
|
// this function should be updated to use NdisRawWritePortBufferUshort
|
|
// when the datarat is capable of handling it!!!!
|
|
//
|
|
VOID
|
|
AdpPutBuffer (
|
|
IDD *idd,
|
|
ULONG Destination,
|
|
PUCHAR Source,
|
|
USHORT Length
|
|
)
|
|
{
|
|
USHORT WordLength = Length >> 1;
|
|
PUCHAR OddData = (PUCHAR)(Source + (Length - 1));
|
|
|
|
D_LOG(D_ENTRY, ("AdpPutBuffer: idd: 0x%lx, Destination: 0x%lx, Source: 0x%lx, Length: %d\n", \
|
|
idd, Destination, Source, Length));
|
|
|
|
AdpSetAddress(idd, Destination);
|
|
|
|
//
|
|
// if WordLength has gone to zero with the shift this macro is just a nop
|
|
//
|
|
NdisRawWritePortBufferUshort((ULONG)(idd->vhw.vbase_io + ADP_REG_DATA_INC),
|
|
(PUSHORT)Source,
|
|
WordLength);
|
|
|
|
//
|
|
// if the length is odd write the last odd byte to adapter
|
|
//
|
|
if (Length & 0x0001)
|
|
NdisRawWritePortUchar((ULONG)idd->vhw.vbase_io + ADP_REG_DATA_INC, *OddData);
|
|
|
|
#if 0
|
|
NdisRawWritePortBufferUchar( (ULONG)idd->vhw.vbase_io + ADP_REG_DATA_INC,
|
|
Source,
|
|
Length );
|
|
#endif
|
|
}
|
|
|
|
//
|
|
// this function should be updated to use NdisRawReadPortBufferUshort
|
|
// when the datarat is capable of handling it!!!!
|
|
//
|
|
VOID
|
|
AdpGetBuffer (
|
|
IDD *idd,
|
|
PUCHAR Destination,
|
|
ULONG Source,
|
|
USHORT Length
|
|
)
|
|
{
|
|
USHORT WordLength = Length >> 1;
|
|
PUCHAR OddData = (PUCHAR)(Destination + (Length - 1));
|
|
|
|
D_LOG(D_ENTRY, ("AdpGetBuffer: idd: 0x%lx, Destination: 0x%lx, Source: 0x%lx, Length: %d\n", \
|
|
idd, Destination, Source, Length));
|
|
|
|
AdpSetAddress(idd, Source);
|
|
|
|
//
|
|
// if WordLength has gone to zero with the shift this macro is just a nop
|
|
//
|
|
NdisRawReadPortBufferUshort((ULONG)(idd->vhw.vbase_io + ADP_REG_DATA_INC),
|
|
(PUSHORT)Destination,
|
|
WordLength);
|
|
|
|
//
|
|
// if the length is odd read the last odd byte from adapter
|
|
//
|
|
if (Length & 0x0001)
|
|
NdisRawReadPortUchar((ULONG)idd->vhw.vbase_io + ADP_REG_DATA_INC, OddData);
|
|
|
|
// NdisRawReadPortBufferUchar((ULONG)idd->vhw.vbase_io + ADP_REG_DATA_INC,
|
|
// Buffer,
|
|
// Length);
|
|
}
|
|
|
|
VOID
|
|
AdpPutUByte(
|
|
IDD *idd,
|
|
ULONG Address,
|
|
UCHAR Value
|
|
)
|
|
{
|
|
AdpSetAddress(idd, Address);
|
|
idd->OutToPort(idd, ADP_REG_DATA_INC, Value);
|
|
}
|
|
|
|
VOID
|
|
AdpPutUShort(
|
|
IDD *idd,
|
|
ULONG Address,
|
|
USHORT Value
|
|
)
|
|
{
|
|
USHORT_UNION us;
|
|
|
|
us.us = Value;
|
|
AdpSetAddress(idd, Address);
|
|
idd->OutToPort(idd, ADP_REG_DATA_INC, us.uc[1]);
|
|
idd->OutToPort(idd, ADP_REG_DATA_INC, us.uc[0]);
|
|
}
|
|
|
|
VOID
|
|
AdpPutULong(
|
|
IDD *idd,
|
|
ULONG Address,
|
|
ULONG Value
|
|
)
|
|
{
|
|
ULONG_UNION ul;
|
|
|
|
ul.ul = Value;
|
|
AdpSetAddress(idd, Address);
|
|
idd->OutToPort(idd, ADP_REG_DATA_INC, ul.uc[3]);
|
|
idd->OutToPort(idd, ADP_REG_DATA_INC, ul.uc[2]);
|
|
idd->OutToPort(idd, ADP_REG_DATA_INC, ul.uc[1]);
|
|
idd->OutToPort(idd, ADP_REG_DATA_INC, ul.uc[0]);
|
|
}
|
|
|
|
UCHAR
|
|
AdpGetUByte(
|
|
IDD *idd,
|
|
ULONG Address
|
|
)
|
|
{
|
|
UCHAR Value;
|
|
|
|
AdpSetAddress(idd, Address);
|
|
|
|
Value = idd->InFromPort(idd, ADP_REG_DATA_INC);
|
|
|
|
return(Value);
|
|
}
|
|
|
|
USHORT
|
|
AdpGetUShort(
|
|
IDD *idd,
|
|
ULONG Address
|
|
)
|
|
{
|
|
USHORT_UNION us;
|
|
|
|
AdpSetAddress(idd, Address);
|
|
us.uc[1] = idd->InFromPort(idd, ADP_REG_DATA_INC);
|
|
us.uc[0] = idd->InFromPort(idd, ADP_REG_DATA_INC);
|
|
|
|
return(us.us);
|
|
}
|
|
|
|
ULONG
|
|
AdpGetULong(
|
|
IDD *idd,
|
|
ULONG Address
|
|
)
|
|
{
|
|
ULONG_UNION ul;
|
|
|
|
AdpSetAddress(idd, Address);
|
|
ul.uc[3] = idd->InFromPort(idd, ADP_REG_DATA_INC);
|
|
ul.uc[2] = idd->InFromPort(idd, ADP_REG_DATA_INC);
|
|
ul.uc[1] = idd->InFromPort(idd, ADP_REG_DATA_INC);
|
|
ul.uc[0] = idd->InFromPort(idd, ADP_REG_DATA_INC);
|
|
|
|
return(ul.ul);
|
|
}
|
|
|
|
VOID
|
|
AdpWriteCommandStatus(
|
|
IDD *idd,
|
|
UCHAR Value
|
|
)
|
|
{
|
|
//
|
|
// setup the address
|
|
//
|
|
AdpSetAddress(idd, ADP_CMD_WINDOW + 1);
|
|
|
|
//
|
|
// put out the value
|
|
//
|
|
idd->OutToPort(idd, ADP_REG_DATA_INC, Value);
|
|
}
|
|
|
|
UCHAR
|
|
AdpReadCommandStatus(
|
|
IDD *idd
|
|
)
|
|
{
|
|
UCHAR Status;
|
|
|
|
//
|
|
// setup the address
|
|
//
|
|
AdpSetAddress(idd, ADP_CMD_WINDOW + 1);
|
|
|
|
//
|
|
// get status
|
|
//
|
|
Status = idd->InFromPort(idd, ADP_REG_DATA_INC);
|
|
|
|
return(Status);
|
|
}
|
|
|
|
VOID
|
|
AdpSetAddress(
|
|
IDD *idd,
|
|
ULONG Address
|
|
)
|
|
{
|
|
ULONG_UNION ul;
|
|
|
|
//
|
|
// Look at the heartbeat on the adapter and determine if it is
|
|
// still beating.
|
|
//
|
|
ul.ul = 0x504;
|
|
idd->OutToPort(idd, ADP_REG_ADDR_LO, ul.uc[0]);
|
|
idd->OutToPort(idd, ADP_REG_ADDR_MID, ul.uc[1]);
|
|
idd->OutToPort(idd, ADP_REG_ADDR_HI, ul.uc[2]);
|
|
|
|
ul.uc[3] = idd->InFromPort(idd, ADP_REG_DATA_INC);
|
|
ul.uc[2] = idd->InFromPort(idd, ADP_REG_DATA_INC);
|
|
ul.uc[1] = idd->InFromPort(idd, ADP_REG_DATA_INC);
|
|
ul.uc[0] = idd->InFromPort(idd, ADP_REG_DATA_INC);
|
|
|
|
D_LOG( D_NEVER, ("Heartbeat: 0x%lx\n", ul.ul) );
|
|
|
|
D_LOG(D_NEVER, ("AdpSetAddress: idd: 0x%lx, Address: 0x%lx\n", \
|
|
idd, Address));
|
|
//
|
|
// setup address
|
|
//
|
|
ul.ul = Address;
|
|
idd->OutToPort(idd, ADP_REG_ADDR_LO, ul.uc[0]);
|
|
idd->OutToPort(idd, ADP_REG_ADDR_MID, ul.uc[1]);
|
|
idd->OutToPort(idd, ADP_REG_ADDR_HI, ul.uc[2]);
|
|
}
|
|
|
|
UCHAR
|
|
IdpGetUByteIO(
|
|
IDD* idd,
|
|
USHORT port
|
|
)
|
|
{
|
|
UCHAR Value;
|
|
|
|
Value = idd->InFromPort(idd, port);
|
|
|
|
return(Value);
|
|
}
|
|
|
|
VOID
|
|
IdpGetBuffer(
|
|
IDD* idd,
|
|
ULONG Bank,
|
|
ULONG Page,
|
|
ULONG Address,
|
|
USHORT Length,
|
|
PUCHAR Buffer
|
|
)
|
|
{
|
|
//
|
|
// address from offset 0 on the bank and page described
|
|
//
|
|
PUCHAR VirtualAddress = idd->vhw.vmem + Address;
|
|
|
|
DbgPrint("IdpGetBuffer: idd: 0x%x, Bank: 0x%x, Page: 0x%x, Address: 0x%x, VirtAddres: 0x%x, Length: 0x%x\n",
|
|
idd, Bank, Page, Address, VirtualAddress, Length);
|
|
|
|
|
|
if (Length > IDP_RAM_PAGE_SIZE)
|
|
Length = IDP_RAM_PAGE_SIZE;
|
|
|
|
//
|
|
// set the bank to the desired bank
|
|
//
|
|
idd->SetBank(idd, (UCHAR)Bank, 1);
|
|
|
|
//
|
|
// set the page to the desired page
|
|
//
|
|
idd->ChangePage(idd, (UCHAR)Page);
|
|
|
|
//
|
|
// get the stuff
|
|
//
|
|
NdisMoveFromMappedMemory((PVOID)Buffer, (PVOID)VirtualAddress, Length);
|
|
}
|
|
|
|
VOID
|
|
IdpPutUByteIO(
|
|
IDD* idd,
|
|
USHORT Port,
|
|
UCHAR Value
|
|
)
|
|
{
|
|
|
|
}
|
|
|
|
VOID
|
|
IdpPutBuffer(
|
|
IDD* idd,
|
|
ULONG Bank,
|
|
ULONG Page,
|
|
ULONG Address,
|
|
USHORT Length,
|
|
PUCHAR Buffer
|
|
)
|
|
{
|
|
|
|
}
|
|
|
|
/*
|
|
* IDD_MC.C - IDD board specific functions for MCIMAC
|
|
*/
|
|
|
|
/* set active bank, control reset state */
|
|
VOID
|
|
IdpMcSetBank(IDD *idd, UCHAR bank, UCHAR run)
|
|
{
|
|
static UCHAR reset_map[] = { 4, 5, 7 };
|
|
static UCHAR run_map[] = { 0, 1, 3 };
|
|
|
|
idd->OutToPort(idd, 1, (UCHAR)(run ? run_map[bank] : reset_map[bank]));
|
|
}
|
|
|
|
/* set active page, control memory mapping */
|
|
VOID
|
|
IdpMcSetPage(IDD *idd, UCHAR page)
|
|
{
|
|
if ( page == IDD_PAGE_NONE )
|
|
idd->OutToPort(idd, 2, 0);
|
|
else
|
|
idd->OutToPort(idd, 2, (UCHAR)(0x80 | page));
|
|
}
|
|
|
|
/* set base memory window, redundent! - already stored by POS */
|
|
VOID
|
|
IdpMcSetBasemem(IDD *idd, ULONG basemem)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* IDD_PC.C - IDD board specific functions for ARIZONA
|
|
*/
|
|
|
|
/* set active bank, control reset state */
|
|
VOID
|
|
AdpSetBank(IDD *idd, UCHAR bank, UCHAR run)
|
|
{
|
|
|
|
}
|
|
|
|
/* set active page, control memory mapping */
|
|
VOID
|
|
AdpSetPage(IDD *idd, UCHAR page)
|
|
{
|
|
|
|
}
|
|
|
|
/* set base memory window, redundent! - already stored by POS */
|
|
VOID
|
|
AdpSetBasemem(IDD *idd, ULONG basemem)
|
|
{
|
|
|
|
}
|
|
|
|
/*
|
|
* IDD_PC.C - IDD board specific functions for PCIMAC
|
|
*/
|
|
|
|
/* set active bank, control reset state */
|
|
VOID
|
|
IdpPcSetBank(IDD *idd, UCHAR bank, UCHAR run)
|
|
{
|
|
//
|
|
// reset map means that the reset bit is held in the bank select register
|
|
//
|
|
static UCHAR reset_map[] = { 4, 5, 7 };
|
|
|
|
//
|
|
// run map means that the reset bit is not set in the bank select register
|
|
//
|
|
static UCHAR run_map[] = { 0, 1, 3 };
|
|
|
|
idd->OutToPort(idd, 4, (UCHAR)(run ? run_map[bank] : reset_map[bank]));
|
|
}
|
|
|
|
/* set active page, control memory mapping */
|
|
VOID
|
|
IdpPcSetPage(IDD *idd, UCHAR page)
|
|
{
|
|
if ( page == IDD_PAGE_NONE )
|
|
idd->OutToPort(idd, 5, 0);
|
|
else
|
|
idd->OutToPort(idd, 5, (UCHAR)(0x80 | page));
|
|
}
|
|
|
|
/* set base memory window, over-writes IRQ to 0! */
|
|
VOID
|
|
IdpPcSetBasemem(IDD *idd, ULONG basemem)
|
|
{
|
|
idd->OutToPort(idd, 6, (UCHAR)(basemem >> 8));
|
|
idd->OutToPort(idd, 7, (UCHAR)(basemem >> 16));
|
|
}
|
|
|
|
|
|
/*
|
|
* IDD_PC4.C - IDD board specific functions for PCIMAC\4
|
|
*/
|
|
|
|
/*
|
|
* set active bank, control reset state
|
|
*
|
|
* this routine makes use of the local data attached to the i/o resource.
|
|
* as local dta is a long, it is used as an image of registers 3,4,x,x
|
|
*/
|
|
VOID
|
|
IdpPc4SetBank(IDD *idd, UCHAR bank, UCHAR run)
|
|
{
|
|
static UCHAR reset_map[] = { 4, 5, 7 };
|
|
static UCHAR run_map[] = { 0, 1, 3 };
|
|
ULONG lreg;
|
|
UCHAR *reg = (UCHAR*)&lreg;
|
|
UCHAR val = run ? run_map[bank] : reset_map[bank];
|
|
|
|
D_LOG(D_ENTRY, ("idd__pc4_set_bank: entry, idd: 0x%lx, bank: 0x%x, run: 0x%x\n", idd, bank, run));
|
|
|
|
/* lock i/o resource, get local data - which is register image */
|
|
res_own(idd->res_io, idd);
|
|
res_get_data(idd->res_io, &lreg);
|
|
|
|
/* the easy way is to switch on bline & write bline specific code */
|
|
switch ( idd->bline )
|
|
{
|
|
case 0 :
|
|
reg[0] = (reg[0] & 0xF0) | val;
|
|
idd->OutToPort(idd, 3, reg[0]);
|
|
break;
|
|
|
|
case 1 :
|
|
reg[0] = (val << 4) | (reg[0] & 0x0F);
|
|
idd->OutToPort(idd, 3, reg[0]);
|
|
break;
|
|
|
|
case 2 :
|
|
reg[1] = (reg[1] & 0xF0) | val;
|
|
idd->OutToPort(idd, 4, reg[1]);
|
|
break;
|
|
|
|
case 3 :
|
|
reg[1] = (val << 4) | (reg[1] & 0x0F);
|
|
idd->OutToPort(idd, 4, reg[1]);
|
|
break;
|
|
}
|
|
|
|
/* return local data, release resource */
|
|
res_set_data(idd->res_io, lreg);
|
|
res_unown(idd->res_io, idd);
|
|
|
|
D_LOG(D_EXIT, ("idd__pc4_set_bank: exit\n"));
|
|
}
|
|
|
|
/* set active page, control memory mapping */
|
|
VOID
|
|
IdpPc4SetPage(IDD *idd, UCHAR page)
|
|
{
|
|
if ( page == IDD_PAGE_NONE )
|
|
idd->OutToPort(idd, 5, 0);
|
|
else
|
|
idd->OutToPort(idd, 5, (UCHAR)(0x80 | page | (UCHAR)(idd->bline << 5)));
|
|
}
|
|
|
|
/* set base memory window, over-writes IRQ to 0! */
|
|
VOID
|
|
IdpPc4SetBasemem(IDD *idd, ULONG basemem)
|
|
{
|
|
idd->OutToPort(idd, 6, (UCHAR)(basemem >> 8));
|
|
idd->OutToPort(idd, 7, (UCHAR)(basemem >> 16));
|
|
}
|
|
|
|
|
|
/*
|
|
* IDD_MEM.C - some memory handling routines
|
|
*/
|
|
|
|
|
|
/* fill a memory block using word moves */
|
|
VOID
|
|
IdpMemset(UCHAR*dst, USHORT val, INT size)
|
|
{
|
|
D_LOG(D_ENTRY, ("idd__memwset: entry, dst: 0x%lx, val: 0x%x, size: 0x%x\n", dst, val, size));
|
|
|
|
// for ( size /= sizeof(USHORT) ; size ; size--, dst++ )
|
|
// NdisMoveToMappedMemory((PVOID)dst, (PVOID)&val, sizeof(USHORT));
|
|
NdisZeroMappedMemory((PVOID)dst, size);
|
|
}
|
|
|
|
/* copy a memory block using word moves */
|
|
VOID
|
|
IdpMemcpy(UCHAR *dst, UCHAR *src, INT size)
|
|
{
|
|
D_LOG(D_ENTRY, ("idd__memwcpy: entry, dst: 0x%lx, src: 0x%lx, size: 0x%x\n", dst, src, size));
|
|
|
|
// for ( size /= sizeof(USHORT) ; size ; size--, dst++, src++ )
|
|
// NdisMoveToMappedMemory((PVOID)dst, (PVOID)src, sizeof(USHORT));
|
|
|
|
NdisMoveToMappedMemory((PVOID)dst, (PVOID)src, size);
|
|
}
|
|
|
|
|
|
|