📄 init.c
字号:
/*
************************************************************************
*
* INIT.C
*
*
* Portions Copyright (C) 1996-2001 National Semiconductor Corp.
* All rights reserved.
* Copyright (C) 1996-2001 Microsoft Corporation. All Rights Reserved.
*
*
*
*************************************************************************
*/
#include "nsc.h"
#include "newdong.h"
#include "init.tmh"
#define SIR 0
#define MIR 1
#define FIR 2
#define NSC_DEMO_IRDA_SPEEDS ( NDIS_IRDA_SPEED_2400 | \
NDIS_IRDA_SPEED_2400 | \
NDIS_IRDA_SPEED_9600 | \
NDIS_IRDA_SPEED_19200 | \
NDIS_IRDA_SPEED_38400 | \
NDIS_IRDA_SPEED_57600 | \
NDIS_IRDA_SPEED_115200 | \
NDIS_IRDA_SPEED_1152K | \
NDIS_IRDA_SPEED_4M )
// NSC PC87108 index registers. See the spec for more info.
//
enum indexRegs {
BAIC_REG = 0,
CSRT_REG = 1,
MCTL_REG = 2,
GPDIR_REG = 3,
GPDAT_REG = 4
};
#define CS_MODE_CONFIG_OFFSET 0x8
const UCHAR bankCode[] = { 0x03, 0x08, 0xE0, 0xE4, 0xE8, 0xEC, 0xF0, 0xF4 };
//////////////////////////////////////////////////////////////////////////
// //
// Function : NSC_WriteBankReg //
// //
// Description: //
// Write a value to the specified register of the specified register //
// bank. //
// //
//////////////////////////////////////////////////////////////////////////
void NSC_WriteBankReg(PUCHAR comBase, UINT bankNum, UINT regNum, UCHAR val)
{
NdisRawWritePortUchar(comBase+3, bankCode[bankNum]);
NdisRawWritePortUchar(comBase+regNum, val);
// Always switch back to reg 0
NdisRawWritePortUchar(comBase+3, bankCode[0]);
}
//////////////////////////////////////////////////////////////////////////
// //
// Function : NSC_ReadBankReg //
// //
// Description: //
// Write the value from the specified register of the specified //
// register bank. //
// //
//////////////////////////////////////////////////////////////////////////
UCHAR NSC_ReadBankReg(PUCHAR comBase, UINT bankNum, UINT regNum)
{
UCHAR result;
NdisRawWritePortUchar(comBase+3, bankCode[bankNum]);
NdisRawReadPortUchar(comBase+regNum, &result);
// Always switch back to reg 0
NdisRawWritePortUchar(comBase+3, bankCode[0]);
return result;
}
typedef struct _SYNC_PORT_ACCESS {
PUCHAR PortBase;
UINT BankNumber;
UINT RegisterIndex;
UCHAR Value;
} SYNC_PORT_ACCESS, *PSYNC_PORT_ACCESS;
VOID
ReadBankReg(
PVOID Context
)
{
PSYNC_PORT_ACCESS PortAccess=(PSYNC_PORT_ACCESS)Context;
NdisRawWritePortUchar(PortAccess->PortBase+3, bankCode[PortAccess->BankNumber]);
NdisRawReadPortUchar(PortAccess->PortBase+PortAccess->RegisterIndex, &PortAccess->Value);
// Always switch back to reg 0
NdisRawWritePortUchar(PortAccess->PortBase+3, bankCode[0]);
return;
}
VOID
WriteBankReg(
PVOID Context
)
{
PSYNC_PORT_ACCESS PortAccess=(PSYNC_PORT_ACCESS)Context;
NdisRawWritePortUchar(PortAccess->PortBase+3, bankCode[PortAccess->BankNumber]);
NdisRawWritePortUchar(PortAccess->PortBase+PortAccess->RegisterIndex, PortAccess->Value);
// Always switch back to reg 0
NdisRawWritePortUchar(PortAccess->PortBase+3, bankCode[0]);
return;
}
VOID
SyncWriteBankReg(
PNDIS_MINIPORT_INTERRUPT InterruptObject,
PUCHAR PortBase,
UINT BankNumber,
UINT RegisterIndex,
UCHAR Value
)
{
SYNC_PORT_ACCESS PortAccess;
ASSERT(BankNumber <= 7);
ASSERT(RegisterIndex <= 7);
PortAccess.PortBase = PortBase;
PortAccess.BankNumber = BankNumber;
PortAccess.RegisterIndex= RegisterIndex;
PortAccess.Value = Value;
NdisMSynchronizeWithInterrupt(
InterruptObject,
WriteBankReg,
&PortAccess
);
return;
}
UCHAR
SyncReadBankReg(
PNDIS_MINIPORT_INTERRUPT InterruptObject,
PUCHAR PortBase,
UINT BankNumber,
UINT RegisterIndex
)
{
SYNC_PORT_ACCESS PortAccess;
ASSERT(BankNumber <= 7);
ASSERT(RegisterIndex <= 7);
PortAccess.PortBase = PortBase;
PortAccess.BankNumber = BankNumber;
PortAccess.RegisterIndex= RegisterIndex;
NdisMSynchronizeWithInterrupt(
InterruptObject,
ReadBankReg,
&PortAccess
);
return PortAccess.Value;
}
BOOLEAN
SyncGetDongleCapabilities(
PNDIS_MINIPORT_INTERRUPT InterruptObject,
UIR * Com,
DongleParam *Dingle
)
{
SYNC_DONGLE Dongle;
Dongle.Com=Com;
Dongle.Dingle=Dingle;
NdisMSynchronizeWithInterrupt(
InterruptObject,
GetDongleCapabilities,
&Dongle
);
return TRUE;
}
UINT
SyncSetDongleCapabilities(
PNDIS_MINIPORT_INTERRUPT InterruptObject,
UIR * Com,
DongleParam *Dingle
)
{
SYNC_DONGLE Dongle;
Dongle.Com=Com;
Dongle.Dingle=Dingle;
NdisMSynchronizeWithInterrupt(
InterruptObject,
SetDongleCapabilities,
&Dongle
);
return 0;
}
typedef struct _SYNC_FIFO_STATUS {
PUCHAR PortBase;
PUCHAR Status;
PULONG Length;
} SYNC_FIFO_STATUS, *PSYNC_FIFO_STATUS;
VOID
GetFifoStatus(
PVOID Context
)
{
PSYNC_FIFO_STATUS FifoStatus=Context;
NdisRawWritePortUchar(FifoStatus->PortBase+3, bankCode[5]);
NdisRawReadPortUchar(FifoStatus->PortBase+FRM_ST, FifoStatus->Status);
*FifoStatus->Length=0;
if (*FifoStatus->Status & ST_FIFO_VALID) {
UCHAR High;
UCHAR Low;
NdisRawReadPortUchar(FifoStatus->PortBase+RFRL_L, &Low);
NdisRawReadPortUchar(FifoStatus->PortBase+RFRL_H, &High);
*FifoStatus->Length = Low;
*FifoStatus->Length |= (ULONG)High << 8;
}
NdisRawWritePortUchar(FifoStatus->PortBase+3, bankCode[0]);
}
BOOLEAN
SyncGetFifoStatus(
PNDIS_MINIPORT_INTERRUPT InterruptObject,
PUCHAR PortBase,
PUCHAR Status,
PULONG Size
)
{
SYNC_FIFO_STATUS FifoStatus;
FifoStatus.PortBase=PortBase;
FifoStatus.Status=Status;
FifoStatus.Length=Size;
NdisMSynchronizeWithInterrupt(
InterruptObject,
GetFifoStatus,
&FifoStatus
);
return (*Status & ST_FIFO_VALID);
}
//////////////////////////////////////////////////////////////////////////
// //
// Function : Ir108ConfigWrite //
// //
// Description: //
// Write the data in the indexed register of the configuration I/O. //
// //
//////////////////////////////////////////////////////////////////////////
void Ir108ConfigWrite(PUCHAR configIOBase, UCHAR indexReg, UCHAR data, BOOLEAN CSMode)
{
UCHAR IndexStore;
if (CSMode)
{
NdisRawWritePortUchar(configIOBase+indexReg, data);
NdisRawWritePortUchar(configIOBase+indexReg, data);
}
else
{
NdisRawReadPortUchar(configIOBase, &IndexStore);
NdisRawWritePortUchar(configIOBase, indexReg);
NdisRawWritePortUchar(configIOBase+1, data);
NdisRawWritePortUchar(configIOBase+1, data);
NdisRawWritePortUchar(configIOBase, IndexStore);
}
}
//////////////////////////////////////////////////////////////////////////
// //
// Function : Ir108ConfigRead //
// //
// Description: //
// Read the data in the indexed register of the configuration I/O. //
// //
//////////////////////////////////////////////////////////////////////////
UCHAR Ir108ConfigRead(PUCHAR configIOBase, UCHAR indexReg, BOOLEAN CSMode)
{
UCHAR data,IndexStore;
if (CSMode)
{
NdisRawReadPortUchar(configIOBase+indexReg, &data);
}
else
{
NdisRawReadPortUchar(configIOBase, &IndexStore);
NdisRawWritePortUchar(configIOBase, indexReg);
NdisRawReadPortUchar(configIOBase+1, &data);
NdisRawWritePortUchar(configIOBase, IndexStore);
}
return (data);
}
//////////////////////////////////////////////////////////////////////////
// //
// Function : NSC_DEMO_Init //
// //
// Description: //
// Set up configuration registers for NSC evaluation board. //
// //
// NOTE: //
// Assumes configuration registers are at I/O addr 0x398. //
// This function configures the demo board to make the SIR UART appear //
// at <comBase>. //
// //
// Called By: //
// OpenCom //
//////////////////////////////////////////////////////////////////////////
BOOLEAN NSC_DEMO_Init(IrDevice *thisDev)
{
UCHAR val;
UCHAR FifoClear;
BOOLEAN CSMode = FALSE;
switch(thisDev->CardType){
case PUMA108:
CSMode = TRUE;
thisDev->portInfo.ConfigIoBaseAddr = thisDev->portInfo.ioBase + CS_MODE_CONFIG_OFFSET;
case PC87108:
// Look for id at startup.
if (!CSMode)
{
NdisRawReadPortUchar(thisDev->portInfo.ConfigIoBaseAddr, &val);
if (val != 0x5A){
if (val == (UCHAR)0xff){
DBGERR(("didn't see PC87108 id (0x5A); got ffh."));
return FALSE;
}
else {
// ID only appears once, so in case we're resetting,
// don't fail if we don't see it.
DBGOUT(("WARNING: didn't see PC87108 id (0x5A); got %xh.",
(UINT)val));
}
}
}
if (CSMode)
{
// base address ignored.
val = 0;
}
else
{
// Select the base address for the UART
switch ((DWORD_PTR)thisDev->portInfo.ioBase){
case 0x3E8: val = 0; break;
case 0x2E8: val = 1; break;
case 0x3F8: val = 2; break;
case 0x2F8: val = 3; break;
default: return FALSE;
}
}
val |= 0x04; // enable register banks
val |= 0x10; // Set the interrupt line to Totempole output.
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr, BAIC_REG, val, CSMode);
// Select interrupt level according to base address,
// following COM port mapping.
// Also select MIR/FIR DMA channels for rcv and xmit.
//
switch (thisDev->portInfo.irq){
case 3: val = 1; break;
case 4: val = 2; break;
case 5: val = 3; break;
case 7: val = 4; break;
case 9: val = 5; break;
case 11: val = 6; break;
case 15: val = 7; break;
default: return FALSE;
}
switch (thisDev->portInfo.DMAChannel){
case 0: val |= 0x08; break;
case 1: val |= 0x10; break;
case 3: val |= 0x18; break;
default:
DBGERR(("Bad rcv dma channel in NSC_DEMO_Init"));
return FALSE;
}
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr, CSRT_REG, val, CSMode);
// Select device-enable and normal-operating-mode.
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr, MCTL_REG, (UCHAR)3, CSMode);
break;
/*
case PC87307:
//
// Select Logical Device 5
//
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr, 0x7, 0x5);
// Disable IO check
//
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr,0x31,0x0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -