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

📄 cs8900.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  ------------------------------------------------------------------------  $Id: cs8900.c,v 1.5.2.2 2003/09/04 18:46:04 joel Exp $  ------------------------------------------------------------------------    My Right Boot, a boot ROM for embedded hardware.   Copyright Cybertec Pty Ltd, 2000  All rights reserved Cybertec Pty Ltd, 2000    COPYRIGHT (c) 1989-1998.  On-Line Applications Research Corporation (OAR).  The license and distribution terms for this file may be  found in the file LICENSE in this distribution or at  http://www.rtems.com/license/LICENSE.  ------------------------------------------------------------------------  CS8900 net boot driver.*/#include <sys/errno.h>#include <string.h>#include <stdio.h>/* #include <target.h>  chris explain what this is to contain and provide a default one */#include "cs8900.h"/*********************************************************** ***********************************************************           BEGIN SECTION OF DEFAULT DEFINES *********************************************************** ***********************************************************//* * Number of devices supported by this driver */#ifndef CS8900_DEVICES#define CS8900_DEVICES 1#endif/* *  This variable really should come from a per device configuration *  table so the base can vary by adapter. */#ifndef CS8900_IO_BASE extern unsigned int bsp_cs8900_io_base;#define CS8900_IO_BASE bsp_cs8900_io_base#endif/* *  This variable really should come from a per device configuration *  table so the base can vary by adapter. */#ifndef CS8900_MEMORY_BASE extern unsigned int bsp_cs8900_memory_base;#define CS8900_MEMORY_BASE bsp_cs8900_memory_base#endif/* *  This could go to a BSP provided callout. */#ifndef WATCHDOG_TOGGLE#define WATCHDOG_TOGGLE() #endif/* *  This variable really should come from a per device configuration *  table so the base can vary by adapter. * *  chris this is probably not a good default  --joel */#ifndef CS8900_RX_QUEUE_SIZE #define CS8900_RX_QUEUE_SIZE 1#endif/*********************************************************** ***********************************************************              END SECTION OF DEFAULT DEFINES *********************************************************** ***********************************************************//* * We expect to be able to read a complete packet into an mbuf. */#if (MCLBYTES < 1520)#error "CS8900 Driver must have MCLBYTES >= 1520"#endif/* * Task event usage. */#define CS8900_RX_OK_EVENT    RTEMS_EVENT_1#define CS8900_TX_START_EVENT RTEMS_EVENT_1#define CS8900_TX_OK_EVENT    RTEMS_EVENT_2#define CS8900_TX_WAIT_EVENT  RTEMS_EVENT_3/* * Our local data. */static cs8900_device cs8900[CS8900_DEVICES];/* * IO Packet Page inteface. */static inline unsigned shortio_pp_get_reg_16 (int dev, unsigned short reg){  cs8900_io_set_reg (dev, CS8900_IO_BASE + CS8900_IO_PACKET_PAGE_PTR,                     0x3000 | CS8900_PPP_AUTO_INCREMENT | reg);  return cs8900_io_get_reg (dev, CS8900_IO_BASE + CS8900_IO_PP_DATA_PORT0);}static inline unsigned longio_pp_get_reg_32 (int dev, unsigned short reg){  cs8900_io_set_reg (dev, CS8900_IO_BASE + CS8900_IO_PACKET_PAGE_PTR,                     0x3000 | CS8900_PPP_AUTO_INCREMENT | reg);  return ((cs8900_io_get_reg (dev, CS8900_IO_BASE + CS8900_IO_PP_DATA_PORT0) << 16) |          cs8900_io_get_reg (dev, CS8900_IO_BASE + CS8900_IO_PP_DATA_PORT1));}static inline voidio_pp_set_reg_16 (int dev, unsigned short reg, unsigned short data){  cs8900_io_set_reg (dev, CS8900_IO_BASE + CS8900_IO_PACKET_PAGE_PTR,                     0x3000 | CS8900_PPP_AUTO_INCREMENT | reg);  cs8900_io_set_reg (dev, CS8900_IO_BASE + CS8900_IO_PP_DATA_PORT0, data);}static inline voidio_pp_set_reg_32 (int dev, unsigned short reg, unsigned long data){  cs8900_io_set_reg (dev, CS8900_IO_BASE + CS8900_IO_PACKET_PAGE_PTR,                     0x3000 | CS8900_PPP_AUTO_INCREMENT | reg);  cs8900_io_set_reg (dev, CS8900_IO_BASE + CS8900_IO_PP_DATA_PORT0, data >> 16);  cs8900_io_set_reg (dev, CS8900_IO_BASE + CS8900_IO_PP_DATA_PORT1, data);}static inline voidio_pp_bit_set_reg_16 (int dev, unsigned short reg, unsigned short mask){  io_pp_set_reg_16 (dev, reg, io_pp_get_reg_16 (dev, reg) | mask);}static inline voidio_pp_bit_clear_reg_16 (int dev, unsigned short reg, unsigned short mask){  io_pp_set_reg_16 (dev, reg, io_pp_get_reg_16 (dev, reg) & ~mask);}/* * Memory Mapped Packet Page interface. */static inline unsigned shortmem_pp_get_reg (int dev, unsigned short reg){  return cs8900_mem_get_reg (dev, CS8900_MEMORY_BASE + reg);}static inline voidmem_pp_set_reg (int dev, unsigned short reg, unsigned short data){  cs8900_mem_set_reg (dev, CS8900_MEMORY_BASE + reg, data);}static inline voidmem_pp_bit_set_reg (int dev, unsigned short reg, unsigned short mask){  mem_pp_set_reg (dev, reg, mem_pp_get_reg (dev, reg) | mask);}static inline voidmem_pp_bit_clear_reg (int dev, unsigned short reg, unsigned short mask){  mem_pp_set_reg (dev, reg, mem_pp_get_reg (dev, reg) & ~mask);}/* * Trace defines and control structures. */ #define CS8900_T_INT         (0)#define CS8900_T_RX_OK       (1)#define CS8900_T_RX_DROPPED  (2)#define CS8900_T_NO_MBUF     (3)#define CS8900_T_NO_CLUSTERS (4)#define CS8900_T_RX_BEGIN    (5)#define CS8900_T_RX_END      (6)#if CS8900_TRACEstatic const char *cs8900_trace_labels[] ={  "int",  "rx ok",  "rx dropped",  "no mbuf",  "no clusters",  "rx begin",  "rx end"};/* * Assumes a micro-second timer such as the Coldfire. */rtems_unsigned32 rtems_read_timer ();static inline voidcs8900_trace (cs8900_device *cs, unsigned short key, unsigned long var){  rtems_interrupt_level level;    rtems_interrupt_disable (level);    if (cs->trace_in < CS8900_TRACE_SIZE)  {    cs->trace_key[cs->trace_in]  = key;    cs->trace_var[cs->trace_in]  = var;    cs->trace_time[cs->trace_in] = rtems_read_timer ();    cs->trace_in++;  }    rtems_interrupt_enable (level);}#else#define cs8900_trace(c, k, v)#endif/* * Bring the chip online. */static voidcs8900_hardware_init (cs8900_device *cs){  unsigned long  prod_id;  unsigned short status;  int            dev = cs->dev;  /*   * Do nothing while the device is calibrating and checking the EEPROM.   * We must wait 20msecs.   */    io_pp_bit_set_reg_16 (dev, CS8900_PP_SelfCTL, CS8900_SELF_CTRL_RESET);  rtems_task_wake_after (TOD_MILLISECONDS_TO_TICKS (20));    status = io_pp_get_reg_16 (dev, CS8900_PP_SelfST);  if (status == 0) {      printf("Reading status register again\n");      status = io_pp_get_reg_16 (dev, CS8900_PP_SelfST);  }      if (((status & CS8900_SELF_STATUS_INITD) == 0) ||      ((status & CS8900_SELF_STATUS_INITD) &&       (status & CS8900_SELF_STATUS_EEPROM_PRESENT) &&       (status & CS8900_SELF_STATUS_SIBUST)))  {    printf ("CS8900: %s. Initialisation aborted.\n",            (status & CS8900_SELF_STATUS_INITD) ?            "EEPROM read/write failed to complete" :            "Failed to complete to reset");          return;  }    /* Probe the device for its ID */  prod_id = io_pp_get_reg_32 (dev, CS8900_PP_PROD_ID);  if ((prod_id >> 16) != CS8900_ESIA_ID)  {    printf ("CS9800: Invalid EISA ID, read product code 0x%08lx\n", prod_id);    return;  }  if ((prod_id & 0x000000ff) != 0)  {    printf ("CS9800: Unsupported product id, read product code 0x%08lx\n",            prod_id);    return;  }  printf ("CS8900 Rev %ld, %s, %s.\n",          (prod_id >> 8) & 0x1f,          status & CS8900_SELF_STATUS_3_3_V ? "3.3V" : "5.0V",          status & CS8900_SELF_STATUS_EEPROM_PRESENT ?          "EEPROM present" : "no EEPROM");  /*   * Switch to memory base accesses as they are faster. No indirect access.   */    io_pp_set_reg_16 (dev, CS8900_PP_MEM_BASE, CS8900_MEMORY_BASE);  io_pp_set_reg_16 (dev, CS8900_PP_MEM_BASE + 2, (CS8900_MEMORY_BASE >> 16) & 0xf);    io_pp_set_reg_16 (dev,                     CS8900_PP_BusCTL,                    CS8900_BUS_CTRL_RESET_RX_DMA |                    CS8900_BUS_CTRL_USE_SA |                    CS8900_BUS_CTRL_MEMORY_ENABLE);  io_pp_set_reg_16 (dev,                     CS8900_PP_BusCTL,                    CS8900_BUS_CTRL_USE_SA |                    CS8900_BUS_CTRL_MEMORY_ENABLE);  /*   * We are now in memory mapped mode.   */  /*   * Program the Line Control register with the mode we want.   *   * No auto detect support at the moment. Only 10BaseT.   */  mem_pp_set_reg (dev, CS8900_PP_LineCFG, CS8900_LINE_CTRL_10BASET);    /*   * Ask the user for the MAC address, the program into the device.   */#define MACO(o) cs->arpcom.ac_enaddr[o]    mem_pp_set_reg (dev, CS8900_PP_IA,                  (((unsigned int) MACO (1)) << 8) |                  ((unsigned int) MACO (0)));  mem_pp_set_reg (dev, CS8900_PP_IA + 2,                  (((unsigned int) MACO (3)) << 8) |                  ((unsigned int) MACO (2)));  mem_pp_set_reg (dev, CS8900_PP_IA + 4,                  (((unsigned int) MACO (5)) << 8) |                  ((unsigned int) MACO (4)));  /*   * Set the Buffer configuration.   */  mem_pp_set_reg (dev, CS8900_PP_BufCFG,                  CS8900_BUFFER_CONFIG_RDY_FOR_TX |                  CS8900_BUFFER_CONFIG_TX_UNDERRUN |                  CS8900_BUFFER_CONFIG_TX_COL_OVF |                  CS8900_BUFFER_CONFIG_RX_MISSED_OVF);  /*   * Set the Receiver configuration.   */  mem_pp_set_reg (dev, CS8900_PP_RxCFG,                  CS8900_RX_CONFIG_RX_OK |                  CS8900_RX_CONFIG_CRC_ERROR |                  CS8900_RX_CONFIG_RUNT|                  CS8900_RX_CONFIG_EXTRA_DATA);  /*   * Set the Receiver control.   */  mem_pp_set_reg (dev, CS8900_PP_RxCTL,                  CS8900_RX_CTRL_RX_OK |                  CS8900_RX_CTRL_MULTICAST |                  CS8900_RX_CTRL_INDIVIDUAL |                  CS8900_RX_CTRL_BROADCAST);    /*   * Set the Transmitter configuration.   */  mem_pp_set_reg (dev, CS8900_PP_TxCFG,                  CS8900_TX_CONFIG_TX_OK |                  CS8900_TX_CONFIG_OUT_OF_WINDOW |                  CS8900_TX_CONFIG_JABBER |                  CS8900_TX_CONFIG_16_COLLISION);  /*   * Attach the interrupt handler.   */  cs8900_attach_interrupt (dev, cs);    /*   * Program the interrupt level we require then enable interrupts.   */  mem_pp_set_reg (dev, CS8900_PP_INT, 0);  mem_pp_bit_set_reg (dev, CS8900_PP_BusCTL,                      CS8900_BUS_CTRL_ENABLE_INT);}rtems_isrcs8900_interrupt (rtems_vector_number v, void *csp){  cs8900_device  *cs = csp;  int            dev = cs->dev;  unsigned short isq = 0;  struct mbuf    *m;  unsigned char  *p;  ++cs->eth_stats.interrupts;  while (1)  {    isq = mem_pp_get_reg (dev, CS8900_PP_ISQ);    cs8900_trace (cs, CS8900_T_INT, isq);    WATCHDOG_TOGGLE ();        /*     * No more interrupts to service.     */    if (isq == 0)      return;        switch (isq & 0x1f)    {      case 0x04:        /*         * RxEvent.         */        ++cs->eth_stats.rx_interrupts;        if (isq & CS8900_RX_EVENT_RX_OK)        {          m = cs->rx_ready_head;          if (m)          {            cs->rx_ready_head = m->m_nextpkt;            if (cs->rx_ready_head == 0)              cs->rx_ready_tail = 0;            m->m_nextpkt = 0;            cs->rx_ready_len--;                        p = mtod (m, unsigned char *);                  m->m_pkthdr.len = cs8900_get_data_block (dev, p);            if (cs->rx_loaded_tail == 0)              cs->rx_loaded_head = m;            else              cs->rx_loaded_tail->m_nextpkt = m;            cs->rx_loaded_tail = m;            cs->rx_loaded_len++;            if (cs->rx_loaded_len == 1)            {              cs8900_trace (cs, CS8900_T_RX_OK, cs->rx_loaded_len);               rtems_event_send (cs->rx_task, CS8900_RX_OK_EVENT);            }          }          else          {            ++cs->eth_stats.rx_dropped;                        cs8900_trace (cs, CS8900_T_RX_DROPPED, cs->rx_loaded_len);                  if (cs->rx_loaded_len == 0)              rtems_event_send (cs->rx_task, CS8900_RX_OK_EVENT);          }        }        else        {          if (isq & CS8900_RX_EVENT_CRC_ERROR)            ++cs->eth_stats.rx_crc_errors;          if (isq & CS8900_RX_EVENT_RUNT)            ++cs->eth_stats.rx_runt_errors;                    if (isq & CS8900_RX_EVENT_EXTRA_DATA)            ++cs->eth_stats.rx_oversize_errors;        }        break;      case 0x08:                /*         * TxEvent.         */        ++cs->eth_stats.tx_interrupts;        if (cs->tx_active)        {          if (isq & CS8900_TX_EVENT_TX_OK)            ++cs->eth_stats.tx_ok;          cs->tx_active = 0;                  rtems_event_send (cs->tx_task, CS8900_TX_OK_EVENT);        }        break;      case 0x0c:                /*         * BufEvent.         */                if (isq & CS8900_BUFFER_EVENT_RDY_FOR_TX)        {          if (cs->tx_active)          {            ++cs->eth_stats.tx_rdy4tx;            rtems_event_send (cs->tx_task, CS8900_TX_WAIT_EVENT);          }        }        else if (isq & CS8900_BUFFER_EVENT_TX_UNDERRUN)        {          ++cs->eth_stats.tx_underrun_errors;          if (cs->tx_active)            rtems_event_send (cs->tx_task, CS8900_TX_OK_EVENT);        }        else if (isq & CS8900_BUFFER_EVENT_SW_INT)        {          ++cs->eth_stats.int_swint_res;        }        break;      case 0x10:                /*         * RxMiss.         */                cs->eth_stats.rx_missed_errors +=          mem_pp_get_reg (dev, CS8900_PP_RxMISS) >> 6;        break;      case 0x12:                /*         * TxCol.         */        cs->eth_stats.tx_collisions +=          mem_pp_get_reg (dev, CS8900_PP_TxCol) >> 6;        break;      default:        break;    }  }  }intcs8900_link_active (int dev){  return ((mem_pp_get_reg (dev, CS8900_PP_LineST) & CS8900_LINE_STATUS_LINK_OK) ?          1 : 0);}static inline voidcs8900_rx_refill_queue (cs8900_device *cs){  struct ifnet          *ifp = &cs->arpcom.ac_if;  struct mbuf           *m;  rtems_interrupt_level level;    /*   * Hold a single queue of mbuf's at the interface. This   * will lower the latency of the driver.   */  while (cs->rx_ready_len < CS8900_RX_QUEUE_SIZE)  {    MGETHDR (m, M_DONTWAIT, MT_DATA);        if (!m)    {      ++cs->eth_stats.rx_no_mbufs;      cs8900_trace (cs, CS8900_T_NO_MBUF, cs->eth_stats.rx_no_mbufs);            return;    }              MCLGET (m, M_DONTWAIT);        if (!m->m_ext.ext_buf)    {      ++cs->eth_stats.rx_no_clusters;      cs8900_trace (cs, CS8900_T_NO_CLUSTERS, cs->eth_stats.rx_no_clusters);            m_free (m);      return;    }    m->m_pkthdr.rcvif = ifp;    m->m_nextpkt = 0;    rtems_interrupt_disable (level);        if (cs->rx_ready_tail == 0)      cs->rx_ready_head = m;    else      cs->rx_ready_tail->m_nextpkt = m;    cs->rx_ready_tail = m;    cs->rx_ready_len++;    rtems_interrupt_enable (level);

⌨️ 快捷键说明

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