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.
956 lines
27 KiB
956 lines
27 KiB
/*
|
|
************************************************************************
|
|
*
|
|
* 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);
|
|
|
|
// Config Base address low and high.
|
|
//
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr,
|
|
0x61,(UCHAR)(thisDev->portInfo.ioBase));
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr,
|
|
0x60,(UCHAR)(thisDev->portInfo.ioBase >> 8));
|
|
|
|
// Set IRQ
|
|
//
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr,
|
|
0x70,(UCHAR)thisDev->portInfo.irq);
|
|
|
|
// Enable Bank Select
|
|
//
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr,0xF0,0x82);
|
|
|
|
// Enable UIR
|
|
//
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr,0x30,0x1);
|
|
break;
|
|
|
|
*/
|
|
case PC87308:
|
|
|
|
// Select Logical Device 5
|
|
//
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr, 0x7, 0x5, FALSE);
|
|
|
|
// Disable IO check
|
|
//
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr,0x31,0x0, FALSE);
|
|
|
|
// Config Base address low and high.
|
|
//
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr,
|
|
0x61,(UCHAR)(thisDev->portInfo.ioBasePhys), FALSE);
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr,
|
|
0x60,(UCHAR)(thisDev->portInfo.ioBasePhys >> 8), FALSE);
|
|
|
|
// Set IRQ
|
|
//
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr,
|
|
0x70,(UCHAR)thisDev->portInfo.irq, FALSE);
|
|
|
|
// Select DMA Channel
|
|
//
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr,
|
|
0x74,thisDev->portInfo.DMAChannel, FALSE);
|
|
|
|
// DeSelect TXDMA Channel
|
|
//
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr,0x75,0x4, FALSE);
|
|
|
|
// Enable Bank Select
|
|
//
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr,0xF0,0x82, FALSE);
|
|
|
|
|
|
// Enable UIR
|
|
//
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr,0x30,0x1, FALSE);
|
|
break;
|
|
|
|
case PC87338:
|
|
// Select Plug and Play mode.
|
|
val = Ir108ConfigRead(thisDev->portInfo.ConfigIoBaseAddr, 0x1B, FALSE);
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr, 0x1B,
|
|
(UCHAR)(val | 0x08), FALSE);
|
|
|
|
// Write the new Plug and Play UART IOBASE register.
|
|
//
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr, 0x46,
|
|
(UCHAR)((thisDev->portInfo.ioBasePhys>>2) & 0xfe), FALSE);
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr, 0x47,
|
|
(UCHAR)((thisDev->portInfo.ioBasePhys>>8) & 0xfc), FALSE);
|
|
|
|
// Enable 14 Mhz clock + Clk Multiplier
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr, 0x51, 0x04, FALSE);
|
|
|
|
// Get Interrup line and shift it four bits;
|
|
//
|
|
val = thisDev->portInfo.irq << 4;
|
|
|
|
// Read the Current Plug and Play Configuration 1 register.
|
|
//
|
|
val |= Ir108ConfigRead(thisDev->portInfo.ConfigIoBaseAddr,0x1C, FALSE);
|
|
|
|
// Write the New Plug and Play Configuration 1 register.
|
|
//
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr, 0x1C, val, FALSE);
|
|
|
|
// Setup 338 DMA.
|
|
//
|
|
switch (thisDev->portInfo.DMAChannel){
|
|
case 0: val = 0x01; break;
|
|
case 1: val = 0x02; break;
|
|
case 2: val = 0x03; break;
|
|
case 3:
|
|
|
|
// Read the Current Plug and Play Configuration 3 register.
|
|
//
|
|
val = Ir108ConfigRead(
|
|
thisDev->portInfo.ConfigIoBaseAddr,0x50, FALSE) | 0x01;
|
|
|
|
// Write the new Plug and Play Configuration 3 register.
|
|
//
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr, 0x50,
|
|
val, FALSE);
|
|
|
|
// Read the Current Plug and Play Configuration 3 register.
|
|
//
|
|
val = Ir108ConfigRead(
|
|
thisDev->portInfo.ConfigIoBaseAddr,0x4C, FALSE) | 0x80;
|
|
|
|
// Write the new Plug and Play Configuration 3 register.
|
|
//
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr, 0x4C,
|
|
val, FALSE);
|
|
val = 0x04;
|
|
break;
|
|
|
|
default:
|
|
DBGERR(("Bad rcv dma channel in NSC_DEMO_Init"));
|
|
return FALSE;
|
|
}
|
|
|
|
// Write the new Plug and Play Configuration 3 register.
|
|
//
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr, 0x4F, val, FALSE);
|
|
|
|
// Read the Current SuperI/O Configuration Register 2 register.
|
|
//
|
|
val = Ir108ConfigRead(thisDev->portInfo.ConfigIoBaseAddr,0x40, FALSE);
|
|
|
|
// Set up UIR/UART2 for Normal Power Mode and Bank select enable.
|
|
//
|
|
val |= 0xE0;
|
|
|
|
// Write the New SuperI/O Configuration Register 2 register.
|
|
//
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr, 0x40, val, FALSE);
|
|
|
|
|
|
// Read the Current SuperI/O Configuration Register 3 register.
|
|
//
|
|
val = Ir108ConfigRead(thisDev->portInfo.ConfigIoBaseAddr,0x50, FALSE);
|
|
|
|
// Set up UIR/UART2 IRX line
|
|
//
|
|
val |= 0x0C;
|
|
|
|
// Write the New SuperI/O Configuration Register 3 register.
|
|
//
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr, 0x50, val, FALSE);
|
|
|
|
// Set the SIRQ1 int to DRQ3 ??? only for EB
|
|
//val = Ir108ConfigRead(thisDev->portInfo.ConfigIoBaseAddr,0x4c) & 0x3f;
|
|
//Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr, 0x4c, val | 0x80);
|
|
|
|
|
|
// Read the Current Function Enable register.
|
|
//
|
|
val = Ir108ConfigRead(thisDev->portInfo.ConfigIoBaseAddr,0x00, FALSE);
|
|
|
|
// Enable UIR/UART2.
|
|
//
|
|
val |= 0x04;
|
|
|
|
// Write the New Function Enable register.
|
|
//
|
|
Ir108ConfigWrite(thisDev->portInfo.ConfigIoBaseAddr, 0x00, val, FALSE);
|
|
break;
|
|
|
|
|
|
} // End of Evaluation board configuration setction.
|
|
|
|
thisDev->UIR_ModuleId = NSC_ReadBankReg(thisDev->portInfo.ioBase, 3, 0);
|
|
|
|
if (thisDev->UIR_ModuleId<0x20)
|
|
{
|
|
// Older revs of the NSC hardware seem to handle 1MB really poorly.
|
|
thisDev->AllowedSpeedMask &= ~NDIS_IRDA_SPEED_1152K;
|
|
}
|
|
|
|
// The UART doesn't appear until we clear and set the FIFO control
|
|
// register.
|
|
|
|
NdisRawWritePortUchar(thisDev->portInfo.ioBase+2, (UCHAR)0x00);
|
|
NdisRawWritePortUchar(thisDev->portInfo.ioBase+2, (UCHAR)0x07);
|
|
|
|
// Set FIR CRC to 32 bits.
|
|
NSC_WriteBankReg(thisDev->portInfo.ioBase, 6, 0, 0x20);
|
|
|
|
// Switch to bank 5
|
|
// clear the status FIFO
|
|
//
|
|
NdisRawWritePortUchar(thisDev->portInfo.ioBase+3, (UCHAR)0xEC);
|
|
FifoClear = 8;
|
|
do {
|
|
NdisRawReadPortUchar(thisDev->portInfo.ioBase+6, &val);
|
|
NdisRawReadPortUchar(thisDev->portInfo.ioBase+7, &val);
|
|
NdisRawReadPortUchar(thisDev->portInfo.ioBase+5, &val);
|
|
FifoClear--;
|
|
} while( (val & 0x80) && (FifoClear > 0) );
|
|
|
|
// Test for newer silicon for support of Frame stop mode
|
|
|
|
#if 0
|
|
if (thisDev->UIR_Mid < 0x16)
|
|
// Change Bit 1 to Default 1
|
|
// 0x40 -> 0x42
|
|
#endif
|
|
NSC_WriteBankReg(thisDev->portInfo.ioBase, 5, 4, 0x40);
|
|
#if 0 // Since we're not currently using the multi-packet send, we don't use frame stop mode.
|
|
else
|
|
//
|
|
// Set FIFO threshold and TX_MS Tx frame end stop mode.
|
|
//
|
|
// Change Bit 1 to Default 1
|
|
// 0x68 -> 0x6a
|
|
NSC_WriteBankReg(thisDev->portInfo.ioBase, 5, 4, 0x60);
|
|
#endif
|
|
|
|
// Set SIR mode in IRCR1.
|
|
// Enable SIR infrared mode in the Non-Extended mode of operation
|
|
NSC_WriteBankReg(thisDev->portInfo.ioBase, 4, 2, 0x0C);
|
|
|
|
// Set max xmit frame size.
|
|
// Need to set value slightly larger so that counter never
|
|
// reaches 0.
|
|
//
|
|
NSC_WriteBankReg(thisDev->portInfo.ioBase, 4, 4,
|
|
(UCHAR)(MAX_NDIS_DATA_SIZE+1));
|
|
NSC_WriteBankReg(thisDev->portInfo.ioBase, 4, 5,
|
|
(UCHAR)((MAX_NDIS_DATA_SIZE+1) >> 8));
|
|
|
|
// Set max rcv frame size.
|
|
// Need to set value slightly larger so that counter never
|
|
// reaches 0.
|
|
//
|
|
NSC_WriteBankReg(thisDev->portInfo.ioBase, 4, 6,
|
|
(UCHAR)(MAX_RCV_DATA_SIZE+FAST_IR_FCS_SIZE));
|
|
NSC_WriteBankReg(thisDev->portInfo.ioBase, 4, 7,
|
|
(UCHAR)((MAX_RCV_DATA_SIZE+FAST_IR_FCS_SIZE) >> 8));
|
|
|
|
// Set extended mode
|
|
//
|
|
NSC_WriteBankReg(thisDev->portInfo.ioBase, 2, 2, 0x03);
|
|
|
|
// Set 32-bit FIFOs
|
|
//
|
|
NSC_WriteBankReg(thisDev->portInfo.ioBase, 2, 4, 0x05);
|
|
|
|
// Enable and reset FIFO's and set the receive FIF0
|
|
// equal to the receive DMA threshold. See if DMA
|
|
// is fast enough for device.
|
|
//
|
|
NSC_WriteBankReg(thisDev->portInfo.ioBase, 0, 2, 0x07);
|
|
|
|
// Restore to Non-Extended mode
|
|
//
|
|
NSC_WriteBankReg(thisDev->portInfo.ioBase, 2, 2, 0x02);
|
|
|
|
|
|
thisDev->portInfo.hwCaps.supportedSpeedsMask = NSC_DEMO_IRDA_SPEEDS;
|
|
thisDev->portInfo.hwCaps.turnAroundTime_usec = DEFAULT_TURNAROUND_usec;
|
|
thisDev->portInfo.hwCaps.extraBOFsRequired = 0;
|
|
|
|
// Initialize thedongle structure before calling
|
|
// GetDongleCapabilities and SetDongleCapabilities for dongle 1.
|
|
//
|
|
thisDev->currentDongle = 1;
|
|
thisDev->IrDongleResource.Signature = thisDev->DongleTypes[thisDev->currentDongle];
|
|
|
|
thisDev->IrDongleResource.ComPort = thisDev->portInfo.ioBase;
|
|
thisDev->IrDongleResource.ModeReq = SIR;
|
|
thisDev->IrDongleResource.XcvrNum = thisDev->currentDongle;
|
|
|
|
// IrDongle = GetDongleCapabilities(thisDev->IrDongleResource);
|
|
SyncGetDongleCapabilities(&thisDev->interruptObj,&thisDev->IrDongleResource,&thisDev->Dingle[0]);
|
|
|
|
// Initialize thedongle structure before calling
|
|
// GetDongleCapabilities and SetDongleCapabilities for dongle 0.
|
|
//
|
|
thisDev->currentDongle = 0;
|
|
thisDev->IrDongleResource.Signature = thisDev->DongleTypes[thisDev->currentDongle];
|
|
|
|
thisDev->IrDongleResource.ComPort = thisDev->portInfo.ioBase;
|
|
thisDev->IrDongleResource.ModeReq = SIR;
|
|
thisDev->IrDongleResource.XcvrNum = 0;
|
|
|
|
// IrDongle = GetDongleCapabilities(IrDongleResource);
|
|
SyncGetDongleCapabilities(&thisDev->interruptObj,&thisDev->IrDongleResource,&thisDev->Dingle[0]);
|
|
|
|
SyncSetDongleCapabilities(&thisDev->interruptObj,&thisDev->IrDongleResource,&thisDev->Dingle[0]);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#if 1
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Function: NSC_DEMO_Deinit //
|
|
// //
|
|
// DUMMY ROUTINE //
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID NSC_DEMO_Deinit(PUCHAR comBase, UINT context)
|
|
{
|
|
|
|
}
|
|
#endif
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Function: NSC_DEMO_SetSpeed //
|
|
// //
|
|
// Description: //
|
|
// Set up the size of FCB, the timer, FIFO, DMA and the IR mode/dongle //
|
|
// speed based on the negotiated speed. //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOLEAN NSC_DEMO_SetSpeed(
|
|
IrDevice *thisDev,
|
|
PUCHAR comBase,
|
|
UINT bitsPerSec,
|
|
UINT context)
|
|
{
|
|
NDIS_STATUS stat;
|
|
UINT fcsSize;
|
|
|
|
LOG("==>NSC_DEMO_SetSpeed %d",bitsPerSec);
|
|
|
|
if (thisDev->FirReceiveDmaActive) {
|
|
|
|
thisDev->FirReceiveDmaActive=FALSE;
|
|
//
|
|
// receive dma is running, stop it
|
|
//
|
|
CompleteDmaTransferFromDevice(
|
|
&thisDev->DmaUtil
|
|
);
|
|
|
|
}
|
|
|
|
|
|
// Make sure the previous packet completely sent out(Not in the TX FIFO)
|
|
// and Txmitter is empty
|
|
// before the bandwidth control
|
|
|
|
|
|
|
|
while((SyncReadBankReg(&thisDev->interruptObj, comBase, 0, 5)& 0x60) != 0x60);
|
|
|
|
//
|
|
|
|
if (bitsPerSec > 115200){
|
|
|
|
fcsSize = (bitsPerSec >= MIN_FIR_SPEED) ?
|
|
FAST_IR_FCS_SIZE : MEDIUM_IR_FCS_SIZE;
|
|
|
|
if(bitsPerSec >= MIN_FIR_SPEED)
|
|
thisDev->IrDongleResource.ModeReq = FIR;
|
|
else
|
|
thisDev->IrDongleResource.ModeReq = MIR;
|
|
|
|
SyncSetDongleCapabilities(&thisDev->interruptObj,&thisDev->IrDongleResource,&thisDev->Dingle[0]);
|
|
|
|
|
|
// Set extended mode and set DMA fairness.
|
|
//
|
|
SyncWriteBankReg(&thisDev->interruptObj, comBase, 2, 2, 0x03);
|
|
|
|
if (thisDev->UIR_ModuleId < 0x16){
|
|
|
|
// Set Timer registers.
|
|
//
|
|
SyncWriteBankReg(&thisDev->interruptObj, comBase, 4, 0, (UCHAR)0x2);
|
|
SyncWriteBankReg(&thisDev->interruptObj, comBase, 4, 1, (UCHAR)0x0);
|
|
}
|
|
else {
|
|
|
|
// Set Timer registers timer has 8 times finer
|
|
// resolution.
|
|
//
|
|
SyncWriteBankReg(&thisDev->interruptObj, comBase, 4, 0, (UCHAR)(TIMER_PERIODS & 0xff));
|
|
SyncWriteBankReg(&thisDev->interruptObj, comBase, 4, 1, (UCHAR)(TIMER_PERIODS >> 8));
|
|
|
|
}
|
|
|
|
// Set max rcv frame size.
|
|
// Need to set value slightly larger so that counter never reaches 0.
|
|
//
|
|
DBGERR(("Programming Max Receive Size registers with %d Bytes ",
|
|
MAX_RCV_DATA_SIZE+fcsSize));
|
|
SyncWriteBankReg(&thisDev->interruptObj, comBase, 4, 6, (UCHAR)(MAX_RCV_DATA_SIZE+fcsSize));
|
|
SyncWriteBankReg(&thisDev->interruptObj, comBase, 4, 7,
|
|
(UCHAR)((MAX_RCV_DATA_SIZE+fcsSize) >> 8));
|
|
|
|
|
|
// Reset Timer Enable bit.
|
|
//
|
|
SyncWriteBankReg(&thisDev->interruptObj, comBase, 4, 2, 0x00);
|
|
|
|
// Set MIR/FIR mode and DMA enable
|
|
//
|
|
SyncWriteBankReg(&thisDev->interruptObj, comBase, 0, 4,
|
|
(UCHAR)((bitsPerSec >= 4000000) ? 0xA4 : 0x84));
|
|
|
|
DBGERR(("EXCR2= 0x%x",SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 2, 4)));
|
|
|
|
// Set 32-bit FIFOs
|
|
//
|
|
SyncWriteBankReg(&thisDev->interruptObj, comBase, 2, 4, 0x05);
|
|
DBGERR(("EXCR2= 0x%x",SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 2, 4)));
|
|
|
|
//
|
|
// We may start receiving immediately so setup the
|
|
// receive DMA
|
|
//
|
|
|
|
|
|
#if 0
|
|
// First, tear down any existing DMA
|
|
if (thisDev->FirAdapterState==ADAPTER_RX) {
|
|
|
|
thisDev->FirAdapterState=ADAPTER_NONE;
|
|
|
|
CompleteDmaTransferFromDevice(
|
|
&thisDev->DmaUtil
|
|
);
|
|
}
|
|
|
|
FindLargestSpace(thisDev, &thisDev->rcvDmaOffset, &thisDev->rcvDmaSize);
|
|
|
|
SetupRecv(thisDev);
|
|
|
|
|
|
// Set the interrupt mask to interrupt on the
|
|
// first packet received.
|
|
//
|
|
thisDev->IntMask = 0x04;
|
|
DBGOUT(("RxDMA = ON"));
|
|
#endif
|
|
}
|
|
else {
|
|
|
|
// Set SIR mode in UART before setting the timing of transciever
|
|
//
|
|
|
|
// Set SIR mode
|
|
//
|
|
SyncWriteBankReg(&thisDev->interruptObj, comBase, 4, 2, 0x0C);
|
|
|
|
// Must set SIR Pulse Width Register to 0 (3/16) as default
|
|
// Bug in 338/108
|
|
SyncWriteBankReg(&thisDev->interruptObj, comBase, 6, 2, 0x0);
|
|
|
|
// Clear extended mode
|
|
//
|
|
SyncWriteBankReg(&thisDev->interruptObj, comBase, 2, 2, 0x00);
|
|
|
|
|
|
thisDev->IrDongleResource.ModeReq = SIR;
|
|
SyncSetDongleCapabilities(&thisDev->interruptObj,&thisDev->IrDongleResource,&thisDev->Dingle[0]);
|
|
|
|
|
|
// Clear Line and Auxiluary status registers.
|
|
//
|
|
SyncReadBankReg(&thisDev->interruptObj, comBase, 0, 5);
|
|
SyncReadBankReg(&thisDev->interruptObj, comBase, 0, 7);
|
|
|
|
}
|
|
LOG("<==NSC_DEMO_SetSpeed");
|
|
return TRUE;
|
|
}
|