📄 16950pci.c
字号:
//-----------------------------------------------------------------------------
// $Id: 16950pci.c,v 1.0.0 2004/01/13
//-----------------------------------------------------------------------------
//
// ProfiM - PROFIBUS MASTER DRIVER FOR WINDOWS NT/2000
//
// Author:
// Pavel Trnka, CTU FEE
// trnkap@seznam.cz
// With help and advices from:
// Ing. Petr Smolik, CTU FEE
// Ing. Pavel Pisa, CTU FEE
// Ing. Pavel Burget, CTU FEE
//
//---------------------------------------------------------------------------
//
// Popis:
// ------
// Funkce pro praci s obvodem 16PCI954. Zajisteni pristupu do rozsirenych
// registru obvodu (Specific Registers a Indexed Control Register Set).
// Funkce pro inicializaci obvodu a nastaveni pozadovaneho rezimu.
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#include "serial_reg.h"
#include "vardef.h"
#define u950pci_inb(base,port) READ_PORT_UCHAR( (PUCHAR) ((base)+(port)) )
#define u950pci_outb(base,port,val) WRITE_PORT_UCHAR( (PUCHAR) ((base)+(port)), (UCHAR) (val) )
//#define u950pci_inb(base,port) DbgPrint( "READ_PORT_UCHAR from port %d\n",( (int) ((base)+(port)) ) )
//#define u950pci_outb(base,port,val) DbgPrint( "WRITE_PORT_UCHAR %d to port %d\n", (int) (val), (int) ((base)+(port)) )
#ifdef AUTOMATIC_RX
#define U950PCI_MCR_IE 0x88 // receive/transmit MCR without change
#define U950PCI_MCR_OE 0x88
#else
#define U950PCI_MCR_IE 0x88 // receive 0x09 for Advantech +Prescaler Enabled
#define U950PCI_MCR_OE 0x89 // transmit 0x08 for Advantech +Prescaler Enabled
#endif
#define U950PCI_MCR_TXDTRPOL 0x01
#define U950PCI_LCR_UL 0x1B /* receive/transmit */ // SET PARAMETERS HERE
#define U950PCI_LCR_ULB 0x5B /* transmit line break */
#define U950PCI_LCR_EFR 0xBF /* enable access to EFR, XONx */
#define U950PCI_LSR_C 0x04 /* controll character received */
#define U950PCI_LSR_ERR 0x1A /* error in receiver */
#define U950PCI_NMR_EN 0x03 /* 9-bit communication settings */
#define U950PCI_IIR_ID 0x3f /* more IRQ levels */
#define U950pci_MSR_RxD UART_MSR_RI /* Pin for RxD level sense */
/* flags of chip options used in u950pci_init */
/* unfortunate random DTR polarity over different vendors !!! */
#define U950PCI_CHOPT_TXDTRNEG 1 /* negated polarity (Advantech) */
#define U950PCI_CHOPT_HSPDOSC 2 /* oscilator 14.7456MHz/1.8432MHz */
#define U950PCI_CHOPT_RXDONRI 4 /* RxD signal connected to RI */
#define U950PCI_ACR_VAL chip_buff[2] /* shaddow buffer of ACR */
/* default ACR value : DTR=1 when Tx, 950 trigger levels enable */
#ifdef AUTOMATIC_RX
#define U950PCI_ACR_UL (UART_ACR_TLENB)
#define U950PCI_ACR_ULTX (U950PCI_ACR_UL|0x10) // 0x18 - automatic DTR control
#define U950PCI_ACR_TXDTRPOL 0x08 /* ^- 0x18 for Advantech */
#else
#define U950PCI_ACR_UL (UART_ACR_TLENB)
#define U950PCI_ACR_ULTX (U950PCI_ACR_UL|0x10|UART_ACR_RXDIS)/**/ // 0x10 ??? - not used in this mode
#define U950PCI_ACR_TXDTRPOL 0x08 /* ^- 0x18 for Advantech */
#endif
#define U950PCI_STATE chip_buff[3] /* chip state information */
#define U950PCI_STATE_TX 1
#define U950PCI_STATE_FLUSH 2
#define U950PCI_RX_ACRMCR chip_buff[4] /* set this for RX - LSB=ACR, MSB=MCR */
#define U950PCI_RX_ACR(udrv) (udrv->U950PCI_RX_ACRMCR)
#define U950PCI_RX_MCR(udrv) ((udrv->U950PCI_RX_ACRMCR>>8))
#define U950PCI_TX_ACRMCR chip_buff[5] /* set this for TX - LSB=ACR, MSB=MCR */
#define U950PCI_TX_ACR(udrv) (udrv->U950PCI_TX_ACRMCR)
#define U950PCI_TX_MCR(udrv) ((udrv->U950PCI_TX_ACRMCR>>8))
//*****************************************************************************
void u950pci_SetBaudRate( PPROFIM_DEVICE_EXTENSION DevExt,
int SC,
int DIV,
int CPR );
void u950pci_GetBaudRateParameters( PPROFIM_DEVICE_EXTENSION DevExt,
LONG XTALFrequency,
LONG BaudRate,
int *SC,
int *DIV,
int *CPR );
void u950pci_RxTreshold( PPROFIM_DEVICE_EXTENSION DevExt, int Treshold );
//*****************************************************************************
//** Funkce umoznujici zapis do registru v Indexed Control Registr Set.
//** Jde o registry ACR, CPR, TCR CKS, TTL, RTL, FCL, FCH, IDx, REV, CSR, NMR,
//** MDM, RFC, GDS.
//**
//** Parametry:
//** index - adresa ciloveho registru ( UART_ACR=0x00 ... UART_GDS=0x10 )
//** val - zapisovana hodnota
//**
//*****************************************************************************
INLINE void u950pci_icr_write( PPROFIM_DEVICE_EXTENSION DevExt,
int index,
int val )
{
u950pci_outb( DevExt->port, UART_SCR, index );
u950pci_outb( DevExt->port, UART_ICR, val );
}
//*****************************************************************************
//** Funkce umoznujici cteni z registru v Indexed Control Registr Set.
//** Jde o registry ACR, CPR, TCR CKS, TTL, RTL, FCL, FCH, IDx, REV, CSR, NMR,
//** MDM, RFC, GDS.
//**
//** Parametry:
//** index - adresa ciloveho registru ( UART_ACR=0x00 ... UART_GDS=0x10 )
//**
//*****************************************************************************
unsigned u950pci_icr_read( PPROFIM_DEVICE_EXTENSION DevExt, int index )
{
unsigned val;
u950pci_icr_write( DevExt,
UART_ACR,
DevExt->U950PCI_ACR_VAL | UART_ACR_ICRRD );
u950pci_outb( DevExt->port, UART_SCR, index );
val = u950pci_inb( DevExt->port, UART_ICR );
u950pci_icr_write( DevExt, UART_ACR, DevExt->U950PCI_ACR_VAL );
return val;
}
//*****************************************************************************
//** Funkce umoznujici cteni registru udavajicich pocet znaku ve vyrovnavacich
//** pametech FIFO. Cteny mohou byt registry:
//**
//** RFL (Number of characters in the receiver FIFO) reg = UART_RFL
//** TFL (Number of characters in the transfimer FIFO) reg = UART_TFL
//**
//*****************************************************************************
unsigned u950pci_xfl_read( PPROFIM_DEVICE_EXTENSION DevExt, int reg )
{
unsigned val;
u950pci_icr_write( DevExt,
UART_ACR,
DevExt->U950PCI_ACR_VAL | UART_ACR_ASREN );
val = u950pci_inb( DevExt->port, reg );
/* no need to set ACR index - SCR not changed */
u950pci_outb( DevExt->port, UART_ICR, DevExt->U950PCI_ACR_VAL );
return val;
}
//*****************************************************************************
//** Zapis do registru ACR
//**
//*****************************************************************************
INLINE void u950pci_acr_write( PPROFIM_DEVICE_EXTENSION DevExt, int val )
{
DevExt->U950PCI_ACR_VAL = val;
u950pci_icr_write( DevExt, UART_ACR, val );
}
//*****************************************************************************
//** 16950pci initialize ports (1st part)
//**
//*****************************************************************************
int u950pci_init( PPROFIM_DEVICE_EXTENSION DevExt,
int port,
int irq,
int baud,
int options )
{
unsigned u;
unsigned old_mcr, mcr_ie;
unsigned chip_id, chip_rev;
if ( !irq || !port )
{
DbgPrint( "ProfiM u950pci_init: port or irq unknown\n" );
return FALSE;
}
DbgPrint( "ProfiM u950pci_init: irq %d port 0x%x\n", irq, port );
old_mcr = u950pci_inb( port, UART_MCR );
/* find right value for mcr_ie */
mcr_ie = U950PCI_MCR_IE;
if ( options & U950PCI_CHOPT_TXDTRNEG )
mcr_ie ^= U950PCI_MCR_TXDTRPOL;
/* Disable output buffer */
u950pci_outb( port, UART_MCR, mcr_ie & 3 );
/* Switch to enhanced mode */
u950pci_outb( port, UART_LCR, U950PCI_LCR_EFR );
u950pci_outb( port, UART_EFR, UART_EFR_ECB );
u950pci_outb( port, UART_LCR, U950PCI_LCR_UL );
/* Disable transmitter output */
u950pci_outb( port, UART_MCR, mcr_ie & 3 );
/* Set up ACR and state */
u950pci_outb( port, UART_SCR, UART_ACR );
u950pci_outb( port, UART_ICR, U950PCI_ACR_UL | UART_ACR_ICRRD );
/* Read chip ID */
u950pci_outb( port, UART_SCR, UART_ID1 );
chip_id = u950pci_inb( port, UART_ICR ) << 16;
u950pci_outb( port, UART_SCR, UART_ID2 );
chip_id |= u950pci_inb( port, UART_ICR ) << 8;
u950pci_outb( port, UART_SCR, UART_ID3 );
chip_id |= u950pci_inb( port, UART_ICR );
u950pci_outb( port, UART_SCR, UART_REV );
chip_rev = u950pci_inb( port, UART_ICR );
DbgPrint( "ProfiM u950pci_init: chip ID %06X. rev %02x\n",
chip_id,
chip_rev );
/* Switch enhancements off */
u950pci_outb( port, UART_LCR, U950PCI_LCR_EFR );
u950pci_outb( port, UART_EFR, 0 );
u950pci_outb( port, UART_LCR, U950PCI_LCR_UL );
{
DbgPrint( "ProfiM u950pci_init: init OK\n" );
DevExt->chip_options = options;
/* setup configurations for RX/TX */
DevExt->U950PCI_RX_ACRMCR = U950PCI_ACR_UL | ( U950PCI_MCR_IE << 8 );
DevExt->U950PCI_TX_ACRMCR = U950PCI_ACR_ULTX | ( U950PCI_MCR_OE << 8 );
if ( DevExt->chip_options & U950PCI_CHOPT_TXDTRNEG )
{
DbgPrint( "ProfiM u950pci_init: ADVANTECH !!!\n" );
DevExt->U950PCI_RX_ACRMCR ^= U950PCI_MCR_TXDTRPOL << 8;
DevExt->U950PCI_TX_ACRMCR ^= U950PCI_ACR_TXDTRPOL |
( U950PCI_MCR_TXDTRPOL << 8 );
}
/* check and setup baud base oscilator frequency */
if ( !DevExt->baud_base )
{
if ( DevExt->chip_options & U950PCI_CHOPT_HSPDOSC )
DevExt->baud_base = 14745600;
else
DevExt->baud_base = 1843200;
// Pro specialni verzi karty pro firmu PiKRON byl na karte vymenen
// krystal za rychlejsi na 24.07342Mhz
if (DevExt->PiKRON)
DevExt->baud_base = 24073420;
DbgPrint( "ProfiM u950pci_init: Oscilator frequency = %ldHz\n",
DevExt->baud_base);
}
if ( !baud )
baud = 9600;
DevExt->baud_val = baud;
u = ( DevExt->baud_base * 8 + baud / 2 ) / baud;
if ( u > 0xFFFFFFF )
u = 0xFFFFFFF;
DevExt->baud_div = u;
DevExt->port = port;
DevExt->irq = irq;
return TRUE;
}
DbgPrint( "ProfiM u950pci_init: MCR test Error\n" );
return FALSE;
};
//*****************************************************************************
//** 16950pci deinitialize ports
//**
//*****************************************************************************
int u950pci_pdone( PPROFIM_DEVICE_EXTENSION DevExt )
{
u950pci_outb( DevExt->port, UART_IER, 0 ); /* disable interrupts */
/* Switch enhanced mode off */
u950pci_outb( DevExt->port, UART_LCR, U950PCI_LCR_EFR );
u950pci_outb( DevExt->port, UART_EFR, 0 );
u950pci_outb( DevExt->port, UART_LCR, U950PCI_LCR_UL );
/* clean up */
u950pci_outb( DevExt->port, UART_IER, 0 ); /* disable interrupts */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -