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

📄 smc8xx.c

📁 这是单板上DPRAM的驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:

        /*-------------------------------------------------------------*/
        /* NULL out descriptor data pointer and length.                */
        /*-------------------------------------------------------------*/
         ring->address = (void *)0;
         ring->length = 0;

        /*-------------------------------------------------------------*/
        /* Wrap descriptor pointer if bottom of ring.                  */
        /*-------------------------------------------------------------*/
         _sync_io();
         if (ring == chan->txrg_bottom)
            {
            ring->status = SMC_TX_WRAP;
            ring = chan->txrg_top;
            }
         else
            {
            ring->status  = 0;
            ring++;
            }

        /*-------------------------------------------------------------*/
        /* Handle end of frame transmission. (transmit interrupt)      */
        /*-------------------------------------------------------------*/
        if (status & SMC_TX_INTR)
           {

            /*---------------------------------------------------------*/
            /* Update transmit tail pointer: must be done prior to     */
            /* call-out *datcnf as this may queue some more data.       */
            /*---------------------------------------------------------*/
            chan->txrg_rd = ring;

            /*---------------------------------------------------------*/
            /* Update the status of the transmitted frame in the status */
            /* field of the buffer descriptor.                         */
            /*---------------------------------------------------------*/
            imask = splx(MAX_ILEV);
            _sync_io();
            mblk = BufListTxRemove(&chan->tx_queue);
            (void)splx(imask);

            chan->tx_count--;


            /*---------------------------------------------------------*/
            /* Return the mblock to the data link layer using the      */
            /* UDataCnf call-out.                                      */
            /*---------------------------------------------------------*/
            DO_DATACNF(mblk, frameFlag);

            /*txstatus    = 0; -del by szg *//* Clear txstatus for next frame */
            frameFlag = 0;     /*  Clear status for next frame */
            }
         }
      else
         break;         /* Not finished sending yet */
      }

/*---------------------------------------------------------------------*/
/* Update transmit tail pointer                                        */
/*---------------------------------------------------------------------*/
   chan->txrg_rd = ring;
}

/***********************************************************************/
/* error_poll:                                                         */
/*             Polls SMC register for error events                      */
/*                                                                     */
/*      INPUTS:                                                        */
/*              chan pointer to the structure that contains channel    */
/*                   information                                       */
/*                                                                     */
/***********************************************************************/
static void
error_poll(chan_control *chan)
{
    smc_regs       *smc_regs;      /* ptr to SMC registers */
    USHORT          status;        /* content of an individual register */
    ULONG           imask;

/*---------------------------------------------------------------------*/
/* Initialize pointer SMC registers                                    */
/*---------------------------------------------------------------------*/
    smc_regs = chan->smc_regs;

/*---------------------------------------------------------------------*/
/* Poll Event register for error conditions - increment error counters */
/* and clear non fatal errors.                                         */
/*---------------------------------------------------------------------*/
    status = smc_regs->smce;

/*---------------------------------------------------------------------*/
/* Clear all set bits of interest. Bit is cleared by writing a 1 to it */
/*---------------------------------------------------------------------*/
   smc_regs->smce = status & ~(SMC_EV_RXBUF | SMC_EV_TXBUF );

   if (status & SMC_EV_BRKRCV )
      {
      /*-------------------------------------------------------------*/
      /* A break condition has ended. (received a break) use the     */
      /* UExcInd call-out to notify the upper layer.                 */
      /* When the break comes from the pROBE console defer until     */
      /* pROBE wakes up and polls us directly via ioctl(BREAKCHECK). */
      /*-------------------------------------------------------------*/
   #if BSP_NUM_SER_DRVRS > 1
      if ( ( chan->port == SDrvCnfg[ ProbeCon ].pnum ) &&
           ( SerialFuncs[ SDrvCnfg[ ProbeCon ].dnum ].Init == smc8xx_Init )
         )
   #else
      if ( chan->port == (ProbeCon - 1) )
   #endif
          serial_break_detected = 1;
      else
         DO_EXPIND(SIOCBREAKR);

      smc_regs->smce = SMC_EV_BRKRCV;
      }

   if (status & SMC_EV_BUSY)
      {
   /*-------------------------------------------------------------*/
   /* Some characters were discarded because of lack of buffers   */
   /* Replenish the receive ring and account for those errors.    */
   /*-------------------------------------------------------------*/

      imask = splx(MAX_ILEV);
      _sync_io();
      replenish_desc(chan);
      (void)splx(imask);


       chan->stats.buffer_shortage++;

       /*--------------------------------------------------------*/
       /* Tell upper layer by using the UExcInd call-out.        */
       /*--------------------------------------------------------*/
       DO_EXPIND(SIOCOVERRUN);
       smc_regs->smce = SMC_EV_BUSY;
       _sync_io();
       }

   return;
}

/***********************************************************************/
/* allocate_brg:                                                       */
/*              This routine is used to allocate a baud rate generator.*/
/*              If the port currently has a generator assigned it will */
/*              free the old one. If the baud rate is not changing,    */
/*              it will simply return the old generator.               */
/*                                                                     */
/*      INPUTS:                                                        */
/*              port        port number                                */
/*              direction   receive/transmit                           */
/*              rate        baud rate                                  */
/*              multiplier  rate multiplier                            */
/*                                                                     */
/*     RETURNS:                                                        */
/*              baud rate generator used                               */
/*                                                                     */
/***********************************************************************/
static int
allocate_brg(UINT chan, UINT rate,UINT multiplier)
{
   UINT   clkdiv;                            /* clock divider for the BRG */
   ULONG  simode;

/*---------------------------------------------------------------------*/
/* Use the most accurate divider, providing it fits                    */
/* in the 12 bits of the register (DIV < 4096)                         */
/* Here is some information about the baud rate calculation math:      */
/* clkdiv is a composite (prescaled) number of 1xBaud or 16xBaud,      */
/* depending on TDCR or RDCR bits being set.                           */
/* Our check is against the system master clock.                       */
/* Some ranges are illegal since we must use 1xBaud clocking for NRZ   */
/* or NRZI.                                                            */
/*---------------------------------------------------------------------*/
    clkdiv = (BspCpuClkRate() * 1000000) / (rate * multiplier) - 1;
    if(clkdiv >= 4096)
       {
       clkdiv =(((BspCpuClkRate() * 1000000)/(16 * rate * multiplier) -1) << 1) | 1;
       }
    else
       clkdiv <<= 1;   

/*---------------------------------------------------------------------*/
/* reset the selected BRG                                              */
/*---------------------------------------------------------------------*/
    R_BRG(chan,AllocBrg[chan]) = RESET_BRG;

/*---------------------------------------------------------------------*/
/* initialize the selected BRG                                         */
/*---------------------------------------------------------------------*/
   R_BRG(chan,AllocBrg[chan]) = USE_BRGCLK | EN_BRG_COUNT | clkdiv;
   _sync_io();

/*---------------------------------------------------------------------*/
/* attach this BRG to the SMC clock (only 3 bits are first reset)      */
/*---------------------------------------------------------------------*/
  simode = R_SIMODE(chan);
  simode &= ~( 7 << ( 12 + ( SmcNum[chan] * 16 ) ) );
  simode |=  ( AllocBrg[chan] << ( 12 + (SmcNum[chan] * 16) ) );
  R_SIMODE(chan) = simode;
  _sync_io();

  return( AllocBrg[chan] );
}

/***********************************************************************/
/* issue_command:                                                      */
/*              This routine will issue a command to the RISC's        */
/*              Command Register. See the RISC section of the 68360    */
/*              manual for timing information on the command           */
/*              register.  By busy-waiting for the chip BEFORE the     */
/*              command is issued, there is no risk of  overlapping    */
/*              commands.                                              */
/*                                                                     */
/*      INPUTS:                                                        */
/*              port port number                                       */
/*              cmd command                                            */
/*                                                                     */
/***********************************************************************/
static void issue_command (UINT port, USHORT cmd)
{
/*---------------------------------------------------------------------*/
/* Issue a command. Three things are needed: The command or opcode     */
/* (bits 8 - 11) the SEMAPHORE_FLAG bit 0 tells RISC there is a        */
/* command to be processed and the Channel Number (CH NUM) bits 4 -    */
/* 7.                                                                  */
/*---------------------------------------------------------------------*/
   /* R_CR(port) = cmd | SEMAPHORE_FLAG | CR_SMC( SmcNum[port] );*/
   CPM_CMD(cmd|CR_SMC(SmcNum[port]));
   _sync_io();
}


/***********************************************************************/
/* disable_interrupts                                                  */
/*              Disable interrupts from port                           */
/*                                                                     */
/*      INPUTS:                                                        */
/*              port logical port number                               */
/*                                                                     */
/***********************************************************************/
static void disable_interrupts(UINT port, UINT dcdint)
{
   switch( SmcNum[port] )
       {
    /*-----------------------------------------------------------------*/
    /* To disable interrupts for any given SMC the SMC# bit and the    */
    /* Port C bit that controls CTS needs to be cleared.               */
    /*-----------------------------------------------------------------*/
        case 0:
            SPLX(R_CIMR(port) &= ~EN_SMC1;)
            break;

        case 1:
            SPLX(R_CIMR(port) &= ~EN_SMC2;)
            break;

#if (BD_HAS_SLAVE == 1)

        case 2:
            SPLX(R_CIMR(port) &= ~EN_SMC1;)
            break;

        case 3:
            SPLX(R_CIMR(port) &= ~EN_SMC2;)
            break;
#endif
        }


}

/******************************************************************

⌨️ 快捷键说明

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