📄 eth860.c
字号:
break;
case 192:
IMMR->brgc1 = B19200; /* 19200 baud */
break;
case 96:
IMMR->brgc1 = B9600; /* 9600 baud */
break;
case 24:
IMMR->brgc1 = B2400; /* 2400 baud */
break;
case 12:
IMMR->brgc1 = B1200; /* 1200 baud */
break;
default:
DEBUG_ERROR("smc_uart_open - bad baud rate = ", EBS_INT1, uinfo->baud_rate, 0);
return(FALSE);
}
IMMR->si_simode = SIMODE_SMC1CS_BRG1; /* BRG 1 */
/* set up rx buffer descriptors - defined in mpc860ad.h */
CurrentRxBuf = 0;
for (i=0; i<SMC1RxBDs; i++)
{
BUFFER_DESCRIPTORS[SMC1_RX_BD+i].flags = BD_SMC_UART_RX_EMPTY | BD_SMC_UART_RX_INTERRUPT;
BUFFER_DESCRIPTORS[SMC1_RX_BD+i].length = 0;
BUFFER_DESCRIPTORS[SMC1_RX_BD+i].buffer = uart_inbuf + (4*i);
}
BUFFER_DESCRIPTORS[SMC1_RX_BD+i-1].flags |= BD_SMC_UART_RX_WRAP;
for (i=0; i<SMC1TxBDs; i++)
{
BUFFER_DESCRIPTORS[SMC1_TX_BD+i].flags = BD_SMC_UART_TX_INTERRUPT;
BUFFER_DESCRIPTORS[SMC1_TX_BD+i].length = 0;
uartTxDCU[i] = os_alloc_packet_input(CFG_RS232_XMBUFSIZE, ETH860_ALLOC); /* get a DCU */
BUFFER_DESCRIPTORS[SMC1_TX_BD+i].buffer = uartTxDCU[i]->data;
}
BUFFER_DESCRIPTORS[SMC1_TX_BD+i-1].flags |= BD_SMC_UART_TX_WRAP;
/******************************************************* */
/* Common To All Protocols Parameter RAM Initialization */
/******************************************************* */
/* Set RXBD pointer in SMC1 parameter ram */
uart_recbd = BUFFER_DESCRIPTORS+SMC1_RX_BD;
bd_union.bd = uart_recbd;
SMC1_PRAM[0].rbase = bd_union.rbase[1]; /* least sig word */
/* Set TXBD pointer in SMC1 parameter ram */
uart_sendbd = (BUFFER_DESCRIPTORS+SMC1_TX_BD);
uart_sentbd = (BUFFER_DESCRIPTORS+SMC1_TX_BD);
bd_union.bd = uart_sendbd;
SMC1_PRAM[0].tbase = bd_union.tbase[1]; /* least sig word */
SMC1_PRAM[0].rfcr = 0x18; /* Byte ordering, DMA FC */
SMC1_PRAM[0].tfcr = 0x18;
SMC1_PRAM[0].mrblr = 1; /* max chars on receive */
SMC1_PRAM[0].max_idl = 0; /* no idle timeout */
SMC1_PRAM[0].brkln = 0;
SMC1_PRAM[0].brkec = 0;
SMC1_PRAM[0].brkcr = 1;
/* Initialize the CP with the new rx and tx parameters */
IMMR->cp_cr = CPCR_INIT_TX_RX_PARAMS |
CPCR_SMC1_DSP1_CH |
CPCR_FLG; /* ISSUE COMMAND */
while ((IMMR->cp_cr & CPCR_FLG) != READY_TO_RX_CMD); /* remove */
/* Interrupts! */
/* set mask bits to enable interrupts*/
IMMR->smc_regs[SMC1_REG].smc_smcm = (SMCE1_BSY | SMCE1_TX | SMCE1_RX);
IMMR->smc_regs[SMC1_REG].smc_smce = 0xFF; /* clear any old event bits */
IMMR->smc_regs[SMC1_REG].smc_smcmr = 0x4820; /* UART mode, 8N1 */
IMMR->smc_regs[SMC1_REG].smc_smcmr = 0x4823; /* Tx, Rx enabled */
rs232_1_enable_ads(1); /* enable rs232 860 boards */
/*---------------------------------------------------------------------- */
/* Clear Pending Interrupts in CIPR -- Clear bits by writing 1 (16-482) */
/*---------------------------------------------------------------------- */
IMMR->cpmi_cipr &= ~CIMR_SMC1; /* Clear any existing pending interrupt */
IMMR->cpmi_cisr = CIMR_SMC1; /* Clear any existing in-service interrupt */
/*--------------------------------------------------- */
/* Enable SMC1 Interrupts to the CP Interrupt */
/* Controller by writing 0x00000010 to CIMR (16-483) */
/*--------------------------------------------------- */
IMMR->cpmi_cimr |= CIMR_SMC1;
return(TRUE);
#else /* (SMC1UART, SMC2UART) */
#error
#endif
}
/* ******************************************************************** */
/* close the UART driver interface. */
/* */
/* This routine is called when the device interface is no longer needed */
/* it should stop the driver from delivering packets to the upper levels */
/* and shut off packet delivery to the network. */
/* */
/* The address of this function must be placed into the "devices" table in */
/* iface.c either at compile time or before a device open is called. */
/* */
/* */
/* Non packet drivers should behave the same way. */
/* */
void smc_uart_close(PIFACE pi)
{
int i;
rs232_1_enable_ads(0); /* disable rs232 860 boards */
/* reset mask bits to disable interrupts*/
IMMR->smc_regs[SMC1_REG].smc_smcm = 0;
IMMR->smc_regs[SMC1_REG].smc_smcmr &= ~0x0003; /* Tx, Rx disabled */
/*--------------------------------------------------- */
/* Disable SMC1 Interrupts to the CP Interrupt */
/* Controller by clearing 0x00000010 in CIMR (16-483) */
/*--------------------------------------------------- */
IMMR->cpmi_cimr &= ~CIMR_SMC1;
/* Return all DCU's back to the system */
for (i=0; i<SMC1TxBDs; i++)
{
os_free_packet(uartTxDCU[i]);
}
}
/*--------------------------------------------------------------------------
*
* FUNCTION NAME: UARTIntHandler
*
* DESCRIPTION:
*
* Process External Interrupt (assumes only interrupts from SMC1)
* Comes here when '860 interrupts us with a received packet.
*
* Main Processing Steps:
*
* (1) Save off SMCE for SMC1 (SMC1 Event Register)
*
* (2) Clear SMC1 Event Register
*
* (3) Test SMC1 Event
*
* (4) Clear SMC1 bit CPM Interrupt In-Service Register
*
*
*
* EXTERNAL EFFECTS: interrupt related registers
*
* PARAMETERS:
*
* vector - interrupt vector (address)
*
* RETURNS: NONE
*
*-------------------------------------------------------------------------*/
void SMCUARTIntHandler(int vector)
{
VUBYTE my_smce1;
/*-------------------------------------- */
/* Grab the SMC event register (16-361) */
/*-------------------------------------- */
my_smce1 = IMMR->smc_regs[SMC1_REG].smc_smce;
/* Clear all events that will be serviced */
IMMR->smc_regs[SMC1_REG].smc_smce = my_smce1;
n_SMC1_interrupts += 1;
if (!(my_smce1 & (SMCE1_BSY | SMCE1_TX | SMCE1_RX)))
{
n_bogus_SMC1_interrupts += 1;
}
if (my_smce1 & SMCE1_RX) /* Character received - signal interrupt task */
{
n_SMC1_RX_interrupts += 1;
smc_receiver(uartInfo);
}
if (my_smce1 & SMCE1_TX) /* Buffer transmitted - signal interrupt task */
{
n_SMC1_TX_interrupts += 1;
// while (!(uart_sentbd->flags & BD_SMC_UART_TX_READY) & (uart_sentbd->length))
// {
n_SMC1_CHARS_out += uart_sentbd->length;
uart_sentbd->length = 0;
if (uart_sentbd->flags & BD_SMC_UART_TX_WRAP)
uart_sentbd = (BUFFER_DESCRIPTORS+SMC1_TX_BD);
else
uart_sentbd++;
// }
ks_invoke_output(uartIface);
}
if (my_smce1 & SMCE1_BSY) /* receive error - no bd's available */
{
n_SMC1_BSY_interrupts += 1;
}
IMMR->cpmi_cisr = CIMR_SMC1; /* Clear any existing in-service interrupt */
}
/* ******************************************************************** */
/* Send serial data via the SMC UART driver interface. */
/* */
/* This routine is called from uart_send or is called directly with a send buffer */
/* and number of characters to send. This routine sends as many as it can and */
/* returns the number sent. Characters are copied into send buffers initialized as */
/* part of buffer descriptors. This routine marks buffers for the 860 SMC to send */
/* while the output ISR re-enables the sent buffers. */
/* */
int smc_uart_send(char *pdata, int n_bytes)
{
int i;
int n_left, n_this_packet;
int n_sent = 0;
char *pbuffer,*pcurrent;
n_left = n_bytes;
pcurrent = pdata;
/* continue to transmit while there are free bd's and there are characters left to go */
while (!(uart_sendbd->flags & BD_SMC_UART_TX_READY) & (uart_sendbd->length==0) & (n_left>0))
{
if(n_left <= CFG_RS232_XMBUFSIZE) /* break send buffer into buffer sized chunks */
n_this_packet = n_left;
else
n_this_packet = CFG_RS232_XMBUFSIZE;
n_sent += n_this_packet;
n_left -= n_this_packet;
/* copy send data into the send buffer descriptor and send it*/
pbuffer = uart_sendbd->buffer;
for(i=0;i<n_this_packet;i++) *pbuffer++ = *pcurrent++;
uart_sendbd->length =(unsigned short)n_this_packet;
uart_sendbd->flags |= BD_SMC_UART_TX_READY;
if (uart_sendbd->flags & BD_SMC_UART_TX_WRAP)
uart_sendbd = (BUFFER_DESCRIPTORS+SMC1_TX_BD);
else
uart_sendbd++;
}
return (n_sent);
}
/* ******************************************************************** */
/* This is the SMC UART input handler called from the SMC interrupt handler. */
/* */
void smc_receiver(PUART_INFO uinfo)
{
byte chr;
PCIRC_BUFF pq;
int start_rx,rx;
start_rx=CurrentRxBuf;
for (;;)
{
if (BUFFER_DESCRIPTORS[SMC1_RX_BD+CurrentRxBuf].flags & BD_SMC_UART_RX_EMPTY)
{
if (BUFFER_DESCRIPTORS[SMC1_RX_BD+CurrentRxBuf].flags & BD_SMC_UART_RX_WRAP)
CurrentRxBuf = 0;
else
CurrentRxBuf += 1;
}
else /* Here we have a buffer that is not empty but we may have error condition */
{
uart_recbd = BUFFER_DESCRIPTORS+SMC1_RX_BD+CurrentRxBuf;
if (uart_recbd->flags & (BD_SMC_UART_RX_OVERRUN |
BD_SMC_UART_RX_PARITY |
BD_SMC_UART_RX_FRAMING ))
{
if (uart_recbd->flags & BD_SMC_UART_RX_OVERRUN)
rs232_error(uinfo->minor_number,0);
if (uart_recbd->flags & BD_SMC_UART_RX_PARITY)
rs232_error(uinfo->minor_number,1);
if (uart_recbd->flags & BD_SMC_UART_RX_FRAMING)
rs232_error(uinfo->minor_number,2);
n_SMC1_ERR_in += 1;
}
else /* Here we have good input */
{
pq = &uinfo->input_queue;
chr=uart_inbuf[(4*CurrentRxBuf)];
/* if buffer is not full, queue it */
if (!cq_full(pq))
{
/* Signal if in raw mode or if it is a framing */
/* character */
cq_enque(pq,chr); /* Que the character */
if (uinfo->raw_mode || (chr == uinfo->framing_char))
{
ks_invoke_interrupt(uinfo->rs232_pi);
}
n_SMC1_CHARS_in += 1;
}
else
{
/* Tell rs232 package that we lost a character */
rs232_error(uinfo->minor_number, 3);
n_SMC1_LOST_in += 1;
}
}
/* Make sure error bits are reset and reset the buffer */
uart_recbd->flags &= ~(BD_SMC_UART_RX_OVERRUN |
B
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -