?? smc8xx.c
字號:
/* @(#) pSOSystem PowerPC/V2.2.2: bsps/devices/serial/smc8xx.c 2.15 97/09/12 13:40:00 */
/***********************************************************************/
/* */
/* MODULE: bsps/devices/serial/smc8xx.c */
/* DATE: 97/09/12 */
/* PURPOSE: MPC8xx SMC driver using DISI interface */
/* */
/*---------------------------------------------------------------------*/
/* */
/* Copyright 1991 - 1997, Integrated Systems, Inc. */
/* ALL RIGHTS RESERVED */
/* */
/* Permission is hereby granted to licensees of Integrated Systems, */
/* Inc. products to use or abstract this computer program for the */
/* sole purpose of implementing a product based on Integrated */
/* Systems, Inc. products. No other rights to reproduce, use, */
/* or disseminate this computer program, whether in part or in */
/* whole, are granted. */
/* */
/* Integrated Systems, Inc. makes no representation or warranties */
/* with respect to the performance of this computer program, and */
/* specifically disclaims any responsibility for any damages, */
/* special or consequential, connected with the use of this program. */
/* */
/*---------------------------------------------------------------------*/
/* */
/***********************************************************************/
#include <psos.h>
#include <pna.h>
#include <gsblk.h>
#include <disi.h>
#include <icontrol/mpc8xx.h>
#include "board.h"
#include <bsp.h>
#include <bspfuncs.h>
#include <serial/smc8xx.h>
#ifndef CPM_CMD
#define SPLX(A) { unsigned long ilev=splx(1); A; splx(ilev); }
#define CPM_CMD(t) {\
unsigned long old=splx(1); \
while ((S_CP_CommandReg& SEMAPHORE_FLAG) == SEMAPHORE_FLAG); \
S_CP_CommandReg =t|SEMAPHORE_FLAG; \
splx(old); \
while ((S_CP_CommandReg& SEMAPHORE_FLAG) == SEMAPHORE_FLAG); }
#endif
/*---------------------------------------------------------------------*/
/* If there is more than one serial driver for the BSP, the drivers */
/* are multiplexed using the ser_mplx.c code and must have different */
/* names for the DISI entry points. The names are changed so that the */
/* Serial prefix is replaced with a chip specific specifier. */
/*---------------------------------------------------------------------*/
#ifndef BSP_NUM_SER_DRVRS
#define BSP_NUM_SER_DRVRS 1
#endif
#if BSP_NUM_SER_DRVRS > 1
extern const SERIAL_FUNCS SerialFuncs[BSP_NUM_SER_DRVRS];
extern SDRVCNFG SDrvCnfg[BSP_SERIAL+1];
#endif
#if BSP_NUM_SER_DRVRS < 2
#define smc8xx_Init SerialInit
#define smc8xx_Open SerialOpen
#define smc8xx_Send SerialSend
#define smc8xx_Close SerialClose
#define smc8xx_Ioctl SerialIoctl
#endif
/***********************************************************************/
/* Conditional Compile Time Constants */
/***********************************************************************/
/*---------------------------------------------------------------------*/
/* Function prototypes */
/*---------------------------------------------------------------------*/
void smc8xx_Init();
static int validate_config(ChannelCfg *);
static int online(chan_control *, UINT);
static int offline(chan_control *);
static void bzero(void *, UINT);
static void stop(chan_control *);
static int init_param(chan_control *);
static int init_regs(chan_control *);
static int init_uart(chan_control *);
static void enable_interrupts(UINT, UINT);
static void disable_interrupts(UINT, UINT);
static void init_rxring(chan_control *);
static void init_txring(chan_control *);
static void flush_rxring(chan_control *);
static void flush_txring(chan_control *);
static void replenish_desc(chan_control *);
static void drop_buffer(chan_control *);
static ULONG smc_isr(chan_control *);
static void error_poll(chan_control *);
static void flush_backup(chan_control *);
static mblk_t *BufJoin (mblk_t *, mblk_t *);
static void BufAdjust(mblk_t *, UINT);
static UINT BufSize (mblk_t *);
static mblk_t *frame_receive(chan_control *, UINT *);
static int frame_transmit(chan_control *, mblk_t *, UINT);
static int hardware_transmit(chan_control *, mblk_t *);
static void buffer_done(chan_control *);
static void service_queue(chan_control *);
static void queue_toseq(chan_control *, UCHAR);
static void poll_toseq(chan_control *);
static int allocate_brg(UINT, UINT, UINT);
static void issue_command(UINT, USHORT);
static int canon_change_only(ChannelCfg *cur_cfg, ChannelCfg *new_cfg);
static void init_uart_RAM_param(chan_control *chan);
/*---------------------------------------------------------------------*/
/* Allocation functions to allocate dual ported ram for Buffer */
/* descriptors. */
/*---------------------------------------------------------------------*/
extern ULONG BspCpuClkRate(void);
extern void dpram_init(void);
extern UCHAR *dpram_alloc(UINT, UINT);
extern void dpram_dealloc(UINT, UCHAR *, UINT);
extern UINT AllocBrg[];
extern UINT SmcNum[];
extern int NumNon_pSOSChan;
extern int Non_pSOSChan[];
extern int ProbeCon;
/*---------------------------------------------------------------------*/
/* GLOBAL STATIC DATA */
/*---------------------------------------------------------------------*/
static int SerialDriverInit; /* driver not yet initialized */
/*---------------------------------------------------------------------*/
/* This is the closure dereference enable vector. Bits in this vector */
/* are referenced in the SCLOSENOFREE macro, so that other components */
/* may safely zero memory allocation pool and not worry about leaks */
/* while closing serial channels. */
/*---------------------------------------------------------------------*/
static int closevec;
static int serial_break_detected;
/*---------------------------------------------------------------------*/
/* control structure declaration */
/*---------------------------------------------------------------------*/
chan_control channels[MAX_SMC]; /* one ctl struct per SMC */
#ifdef USE_UNCACHE_SECTION
#pragma use_section UNCACHE channels
#endif
/***********************************************************************/
/* init_rxring: */
/* This routine clears the rcv descriptor ring. All */
/* descriptors are marked for the CPU by clearing */
/* the EMPTY bit. The receiver should be stopped before */
/* this routine is executed. */
/* */
/* INPUTS: */
/* chan pointer to the structure that contains channel */
/* information */
/* */
/***********************************************************************/
static void
init_rxring(chan_control *chan)
{
BuffDescType *ring; /* descriptor entry pointer */
/*---------------------------------------------------------------------*/
/* Init all ring structure pointers */
/*---------------------------------------------------------------------*/
ring = chan->rxrg_ep = chan->rxrg_wr = chan->rxrg_rd = chan->rxrg_top;
chan->rxrg_bottom = chan->rxrg_top + chan->MaxBuffers -1;
chan->unused_rx = 0;
/*---------------------------------------------------------------------*/
/* Clear all descriptor buffer pointers and flags bits (except the */
/* WRAP bit on the last entry). */
/*---------------------------------------------------------------------*/
_sync_io();
while (ring != chan->rxrg_bottom)
{
ring->address = (void *)0;
ring->length = 0;
ring->status = 0;
ring++;
_sync_io();
}
chan->rxrg_bottom->address = (void *)0;
chan->rxrg_bottom->length = 0;
chan->rxrg_bottom->status = SMC_TX_WRAP;
_sync_io();
}
/***********************************************************************/
/* init_txring: */
/* This routine clears the transmit descriptor ring. */
/* All descriptors are marked for the CPU by clearing */
/* the READY bit. The transmitter should be stopped */
/* before this routine is executed. */
/* */
/* INPUTS: */
/* chan pointer to the structure that contains channel */
/* information */
/* */
/***********************************************************************/
static void
init_txring(chan_control *chan)
{
BuffDescType *ring; /* descriptor entry pointer */
/*---------------------------------------------------------------------*/
/* Init all ring structure pointers. */
/*---------------------------------------------------------------------*/
ring = chan->txrg_wr = chan->txrg_rd = chan->txrg_top;
chan->txrg_bottom = chan->txrg_top + (chan->MaxBuffers -1);
chan->unused_tx = chan->MaxBuffers;
/*---------------------------------------------------------------------*/
/* Clear all descriptor buffer pointers and status bits (except the */
/* WRAP bit on the last entry). */
/*---------------------------------------------------------------------*/
_sync_io();
while (ring != chan->txrg_bottom)
{
ring->address = (void *)0;
ring->length = 0;
ring->status = 0;
ring++;
_sync_io();
}
chan->txrg_bottom->address = (void *)0;
chan->txrg_bottom->length = 0;
chan->txrg_bottom->status = SMC_TX_WRAP;
_sync_io();
}
/***********************************************************************/
/* flush_rxring: */
/* This routine flushes the receive descriptor ring by */
/* returning all buffers to the free pool. The */
/* receiver should be stopped before this routine is */
/* executed. */
/* */
/* INPUTS: */
/* chan pointer to the structure that contains channel */
/* information */
/* */
/***********************************************************************/
static void
flush_rxring(chan_control *chan)
{
BuffDescType *ring; /* pointer to rx descriptor ring */
mblk_t *buffer; /* actual buffer structure */
ULONG imask; /* slpx saved level */
/*---------------------------------------------------------------------*/
/* Get current read pointer to descriptor ring. */
/*---------------------------------------------------------------------*/
ring = chan->rxrg_rd;
/*---------------------------------------------------------------------*/
/* Delete everything from the receive descriptor ring and */
/* return buffers to free pool. */
/* Go through the ring until a null buffer pointer is found. */
/*---------------------------------------------------------------------*/
while (ring->address != (void *)0)
{
/*-----------------------------------------------------------------*/
/* Clear the Buffer Descriptor data pointer and data length. */
/*-----------------------------------------------------------------*/
ring->address = (void *)0;
ring->length = 0;
/*-----------------------------------------------------------------*/
/* The rx_queue contains a list of actual mblk_t structures, */
/* it operates in parallel to the receive ring. */
/* The macro BufListRxRemove will remove the first mblk_t */
/* structure from the rx_queue and return the pointer that */
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -