⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smc8xx.c

📁 这是单板上DPRAM的驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
/* @(#) 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         */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -