diff options
Diffstat (limited to '')
-rw-r--r-- | bsps/shared/net/cs8900.c | 1216 | ||||
-rw-r--r-- | bsps/shared/net/cs8900.c.bsp | 510 |
2 files changed, 0 insertions, 1726 deletions
diff --git a/bsps/shared/net/cs8900.c b/bsps/shared/net/cs8900.c deleted file mode 100644 index 452a33a372..0000000000 --- a/bsps/shared/net/cs8900.c +++ /dev/null @@ -1,1216 +0,0 @@ -/* - ------------------------------------------------------------------------ - - Copyright Cybertec Pty Ltd, 2000 - All rights reserved Cybertec Pty Ltd, 2000 - - Port to the DIMM PC copyright (c) 2004 Angelo Fraietta - This project has been assisted by the Commonwealth Government - through the Australia Council, its arts funding and advisory body. - - 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.org/license/LICENSE. - - ------------------------------------------------------------------------ - - CS8900 RTEMS driver. - - See the header file for details. - -*/ - -#include <machine/rtems-bsd-kernel-space.h> - -#include <errno.h> -#include <string.h> -#include <stdio.h> - -#include <libchip/cs8900.h> - -/* - * 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 - -/* - * IO Packet Page inteface. - */ - -static inline unsigned short -io_pp_get_reg_16 (cs8900_device *cs, unsigned short reg) -{ - rtems_interrupt_level level; - unsigned short data; - rtems_interrupt_disable (level); - cs8900_io_set_reg (cs, CS8900_IO_PACKET_PAGE_PTR, - 0x3000 | CS8900_PPP_AUTO_INCREMENT | reg); - data = cs8900_io_get_reg (cs, CS8900_IO_PP_DATA_PORT0); - rtems_interrupt_enable (level); - return data; -} - -static inline uint32_t -io_pp_get_reg_32 (cs8900_device *cs, uint16_t reg) -{ - rtems_interrupt_level level; - uint32_t data; - rtems_interrupt_disable (level); - cs8900_io_set_reg (cs, CS8900_IO_PACKET_PAGE_PTR, - 0x3000 | CS8900_PPP_AUTO_INCREMENT | reg); - data = cs8900_io_get_reg (cs, CS8900_IO_PP_DATA_PORT0); - data <<= 16; - data |= cs8900_io_get_reg (cs, CS8900_IO_PP_DATA_PORT1); - rtems_interrupt_enable (level); - return data; -} - -static inline void -io_pp_set_reg_16 (cs8900_device *cs, unsigned short reg, unsigned short data) -{ - rtems_interrupt_level level; - rtems_interrupt_disable (level); - cs8900_io_set_reg (cs, CS8900_IO_PACKET_PAGE_PTR, - 0x3000 | CS8900_PPP_AUTO_INCREMENT | reg); - cs8900_io_set_reg (cs, CS8900_IO_PP_DATA_PORT0, data); - rtems_interrupt_enable (level); -} - -static inline void -io_pp_set_reg_32 (cs8900_device *cs, unsigned short reg, unsigned long data) -{ - cs8900_io_set_reg (cs, CS8900_IO_PACKET_PAGE_PTR, - 0x3000 | CS8900_PPP_AUTO_INCREMENT | reg); - cs8900_io_set_reg (cs, CS8900_IO_PP_DATA_PORT0, data >> 16); - cs8900_io_set_reg (cs, CS8900_IO_PP_DATA_PORT1, data); -} - -static inline void -io_pp_bit_set_reg_16 (cs8900_device *cs, unsigned short reg, unsigned short mask) -{ - rtems_interrupt_level level; - rtems_interrupt_disable (level); - io_pp_set_reg_16 (cs, reg, io_pp_get_reg_16 (cs, reg) | mask); - rtems_interrupt_enable (level); -} - -static inline void -io_pp_bit_clear_reg_16 (cs8900_device *cs, unsigned short reg, unsigned short mask) -{ - rtems_interrupt_level level; - rtems_interrupt_disable (level); - io_pp_set_reg_16 (cs, reg, io_pp_get_reg_16 (cs, reg) & ~mask); - rtems_interrupt_enable (level); -} - -/* - * Memory Mapped Packet Page interface. - * - * If the BSP does not configure mem_base use the I/O register accesses. - */ - -static inline unsigned short -mem_pp_get_reg (cs8900_device *cs, unsigned short reg) -{ - if (!cs->mem_base) - return io_pp_get_reg_16 (cs, reg); - return cs8900_mem_get_reg (cs, reg); -} - -static inline void -mem_pp_set_reg (cs8900_device *cs, unsigned short reg, unsigned short data) -{ - if (!cs->mem_base) - io_pp_set_reg_16 (cs, reg, data); - else - cs8900_mem_set_reg (cs, reg, data); -} - -static inline void -mem_pp_bit_set_reg (cs8900_device *cs, unsigned short reg, unsigned short mask) -{ - if (!cs->mem_base) - io_pp_bit_set_reg_16 (cs, reg, mask); - else - { - rtems_interrupt_level level; - rtems_interrupt_disable (level); - mem_pp_set_reg (cs, reg, mem_pp_get_reg (cs, reg) | mask); - rtems_interrupt_enable (level); - } -} - -static inline void -mem_pp_bit_clear_reg (cs8900_device *cs, unsigned short reg, unsigned short mask) -{ - if (!cs->mem_base) - io_pp_bit_clear_reg_16 (cs, reg, mask); - else - { - rtems_interrupt_level level; - rtems_interrupt_disable (level); - mem_pp_set_reg (cs, reg, mem_pp_get_reg (cs, reg) & ~mask); - rtems_interrupt_enable (level); - } -} - -/* - * 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_TRACE - -static 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. - */ - -uint32_t rtems_read_timer (); - -static inline void -cs8900_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 - -void cs8900_get_mac_addr (cs8900_device *cs, unsigned char *mac_address) -{ - unsigned short ma; - - /* - * Only ever use IO calls for this function as it can be - * called before memory mode has been enabled. - */ - - ma = io_pp_get_reg_16 (cs, CS8900_PP_IA); - mac_address[0] = ma >> 8; - mac_address[1] = ma; - - ma = io_pp_get_reg_16 (cs, CS8900_PP_IA + 2); - mac_address[2] = ma >> 8; - mac_address[3] = ma; - - ma = io_pp_get_reg_16 (cs, CS8900_PP_IA + 4); - mac_address[4] = ma >> 8; - mac_address[5] = ma; -} - -/* - * Bring the chip online. - */ - -static void -cs8900_hardware_init (cs8900_device *cs) -{ - unsigned long prod_id; - unsigned short status; - - /* - * Do nothing while the device is calibrating and checking the EEPROM. - * We must wait 20msecs. - */ - - io_pp_bit_set_reg_16 (cs, CS8900_PP_SelfCTL, CS8900_SELF_CTRL_RESET); - - rtems_task_wake_after (RTEMS_MILLISECONDS_TO_TICKS (20)); - - status = io_pp_get_reg_16 (cs, CS8900_PP_SelfST); - if (status == 0) { - printf("Reading status register again\n"); - status = io_pp_get_reg_16 (cs, 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; - } - - /* Set the RX queue size if not set by the BSP. */ - - if (cs->rx_queue_size == 0) - cs->rx_queue_size = 10; - - /* Probe the device for its ID */ - - prod_id = io_pp_get_reg_32 (cs, CS8900_PP_PROD_ID); - - if ((prod_id >> 16) != CS8900_ESIA_ID) - { - printf ("CS8900: Invalid EISA ID, read product code 0x%08lx\n", prod_id); - return; - } - - if ((prod_id & 0x000000ff) != 0) - { - printf ("CS8900: 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. - */ - - if (cs->mem_base) - { - io_pp_set_reg_16 (cs, CS8900_PP_MEM_BASE, cs->mem_base); - io_pp_set_reg_16 (cs, CS8900_PP_MEM_BASE + 2, (cs->mem_base >> 16) & 0xf); - - io_pp_set_reg_16 (cs, - CS8900_PP_BusCTL, - CS8900_BUS_CTRL_RESET_RX_DMA | - CS8900_BUS_CTRL_USE_SA | - CS8900_BUS_CTRL_MEMORY_ENABLE); - io_pp_set_reg_16 (cs, - 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 (cs, 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 (cs, CS8900_PP_IA, - (((unsigned int) MACO (1)) << 8) | - ((unsigned int) MACO (0))); - mem_pp_set_reg (cs, CS8900_PP_IA + 2, - (((unsigned int) MACO (3)) << 8) | - ((unsigned int) MACO (2))); - mem_pp_set_reg (cs, CS8900_PP_IA + 4, - (((unsigned int) MACO (5)) << 8) | - ((unsigned int) MACO (4))); - - /* - * Set the Buffer configuration. - */ - - mem_pp_set_reg (cs, 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 (cs, 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 (cs, 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 (cs, 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 (cs); - - /* - * Program the interrupt level we require then enable interrupts. - * - * Note, this will need to change to support other levels. - */ - - mem_pp_set_reg (cs, CS8900_PP_INT, cs->irq_level & 3); - - mem_pp_bit_set_reg (cs, CS8900_PP_BusCTL, - CS8900_BUS_CTRL_ENABLE_INT); -} - -rtems_isr -cs8900_interrupt (rtems_vector_number v, void *csp) -{ - cs8900_device *cs = csp; - unsigned short isq = 0; - struct mbuf *m; - unsigned char *p; - - ++cs->eth_stats.interrupts; - - while (1) - { - isq = mem_pp_get_reg (cs, CS8900_PP_ISQ); - - cs8900_trace (cs, CS8900_T_INT, isq); - - /* - * 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 (cs, 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_bsdnet_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_bsdnet_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_bsdnet_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_bsdnet_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_bsdnet_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 (cs, CS8900_PP_RxMISS) >> 6; - break; - - case 0x12: - - /* - * TxCol. - */ - - cs->eth_stats.tx_collisions += - mem_pp_get_reg (cs, CS8900_PP_TxCol) >> 6; - break; - - default: - break; - } - } - -} - -int -cs8900_link_active (cs8900_device *cs) -{ - return ((mem_pp_get_reg (cs, CS8900_PP_LineST) & CS8900_LINE_STATUS_LINK_OK) ? - 1 : 0); -} - -static inline void -cs8900_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 < cs->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); - } -} - -static void -cs8900_rx_task (void *arg) -{ - cs8900_device *cs = arg; - struct ifnet *ifp = &cs->arpcom.ac_if; - rtems_event_set events; - struct mbuf *m; - struct ether_header *eh; - rtems_status_code sc; - rtems_interrupt_level level; - - /* - * Turn the receiver and transmitter on. - */ - - mem_pp_bit_set_reg (cs, CS8900_PP_LineCFG, - CS8900_LINE_CTRL_RX_ON | - CS8900_LINE_CTRL_TX_ON); - - /* - * Start the software interrupt watchdog. - */ - - mem_pp_bit_set_reg (cs, CS8900_PP_BufCFG, - CS8900_BUFFER_CONFIG_SW_INT); - ++cs->eth_stats.int_swint_req; - - /* - * Loop reading packets. - */ - - while (1) - { - cs8900_rx_refill_queue (cs); - - sc = rtems_bsdnet_event_receive (CS8900_RX_OK_EVENT, - RTEMS_WAIT | RTEMS_EVENT_ANY, - RTEMS_MILLISECONDS_TO_TICKS (250), - &events); - - cs8900_rx_refill_queue (cs); - - if (sc == RTEMS_TIMEOUT) - { - /* - * We need to check the interrupt hardware in the cs8900a - * has not locked up. It seems this occurs if the ISQ - * queue fills up. - * To test we generate a software interrupt and watch - * a counter go up. If the counter does not go for 2 - * software interrupts requests we flush the ISQ queue. - */ - - if ((cs->eth_stats.int_swint_req - cs->eth_stats.int_swint_res) > 1) - { - printf ("cs8900: int lockup, isq flush\n"); - - mem_pp_bit_clear_reg (cs, CS8900_PP_BusCTL, - CS8900_BUS_CTRL_ENABLE_INT); - - while (mem_pp_get_reg (cs, CS8900_PP_ISQ) != 0); - - cs->eth_stats.int_swint_req = cs->eth_stats.int_swint_res = 0; - ++cs->eth_stats.int_lockup; - - mem_pp_bit_set_reg (cs, CS8900_PP_BusCTL, - CS8900_BUS_CTRL_ENABLE_INT); - } - - mem_pp_bit_set_reg (cs, CS8900_PP_BufCFG, - CS8900_BUFFER_CONFIG_SW_INT); - ++cs->eth_stats.int_swint_req; - } - - cs8900_trace (cs, CS8900_T_RX_BEGIN, cs->rx_loaded_len); - - while (cs->rx_loaded_len) - { - rtems_interrupt_disable (level); - - m = cs->rx_loaded_head; - if (m) - { - cs->rx_loaded_head = m->m_nextpkt; - if (cs->rx_loaded_head == 0) - cs->rx_loaded_tail = 0; - m->m_nextpkt = 0; - cs->rx_loaded_len--; - - rtems_interrupt_enable (level); - - m->m_pkthdr.rcvif = ifp; - - cs->eth_stats.rx_bytes += m->m_pkthdr.len; - - m->m_len = m->m_pkthdr.len = m->m_pkthdr.len - sizeof (struct ether_header); - - eh = mtod (m, struct ether_header *); - m->m_data += sizeof (struct ether_header); - - ++cs->eth_stats.rx_packets; - - ether_input (ifp, eh, m); - } - else - { - rtems_interrupt_enable (level); - } - } - cs8900_trace (cs, CS8900_T_RX_END, cs->rx_loaded_len); - } -} - -static void -cs8900_tx_task (void *arg) -{ - cs8900_device *cs = arg; - struct ifnet *ifp = &cs->arpcom.ac_if; - rtems_event_set events; - struct mbuf *m; - rtems_status_code sc; - - /* - * Wait for the link to come up. - */ - - rtems_task_wake_after (RTEMS_MILLISECONDS_TO_TICKS (750)); - - /* - * Loop processing the tx queue. - */ - - while (1) - { - /* - * Fetch the mbuf list from the interface's queue. - */ - - IF_DEQUEUE (&ifp->if_snd, m); - - /* - * If something actually is present send it. - */ - - if (!m) - { - ifp->if_flags &= ~IFF_OACTIVE; - - rtems_bsdnet_event_receive (CS8900_TX_START_EVENT, - RTEMS_WAIT | RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - } - else - { - if (cs8900_link_active (cs)) - { - int resending; - - do - { - unsigned short buf_status; - - resending = 0; - - cs->tx_active = 1; - - mem_pp_set_reg (cs, CS8900_PP_TxCMD, - CS8900_TX_CMD_STATUS_TX_START_ENTIRE | - CS8900_TX_CMD_STATUS_FORCE); - mem_pp_set_reg (cs, CS8900_PP_TxLength, m->m_pkthdr.len); - - buf_status = mem_pp_get_reg (cs, CS8900_PP_BusST); - - /* - * If the bid for memory in the device fails trash the - * transmit and try again next time. - */ - - if (buf_status & CS8900_BUS_STATUS_TX_BID_ERROR) - ++cs->eth_stats.tx_bid_errors; - else - { - /* - * If the buffer is not read enable the interrupt and then wait. - */ - - if ((buf_status & CS8900_BUS_STATUS_RDY_FOR_TX_NOW) == 0) - { - cs->eth_stats.tx_wait_for_rdy4tx++; - sc = rtems_bsdnet_event_receive (CS8900_TX_WAIT_EVENT, - RTEMS_WAIT | RTEMS_EVENT_ANY, - RTEMS_MILLISECONDS_TO_TICKS (750), - &events); - if (sc == RTEMS_TIMEOUT) - { - /* - * For some reason the wait request has been dropped, - * so lets resend from the start. - */ - - printf ("tx resend\n"); - ++cs->eth_stats.tx_resends; - resending = 1; - } - } - - if (!resending) - { - cs8900_tx_load (cs, m); - cs->eth_stats.tx_packets++; - cs->eth_stats.tx_bytes += m->m_pkthdr.len; - } - } - } - while (resending); - - m_freem (m); - - do - { - rtems_bsdnet_event_receive (CS8900_TX_OK_EVENT, - RTEMS_WAIT | RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - } - while (cs->tx_active); - } - else - { - ++cs->eth_stats.tx_dropped; - m_freem (m); - } - } - } -} - -static void -cs8900_start (struct ifnet *ifp) -{ - cs8900_device *cs = ifp->if_softc; - - /* - * Tell the transmit daemon to wake up and send a packet. - */ - - ifp->if_flags |= IFF_OACTIVE; - - rtems_bsdnet_event_send (cs->tx_task, CS8900_TX_START_EVENT); -} - -static void -cs8900_stop (cs8900_device *cs) -{ - mem_pp_bit_clear_reg (cs, CS8900_PP_LineCFG, - CS8900_LINE_CTRL_RX_ON | - CS8900_LINE_CTRL_TX_ON); - - mem_pp_bit_clear_reg (cs, CS8900_PP_BusCTL, - CS8900_BUS_CTRL_ENABLE_INT); -} - -static const char *eth_statistics_labels[] = -{ - "rx packets", - "tx packets", - "rx bytes", - "tx bytes", - "rx interrupts", - "tx interrupts", - "rx dropped", - "rx no mbuf", - "rx no custers", - "rx oversize errors", - "rx crc errors", - "rx runt errors", - "rx missed errors", - "tx ok", - "tx collisions", - "tx bid errors", - "tx wait for rdy4tx", - "tx rdy4tx", - "tx underrun errors", - "tx dropped", - "tx resends", - "int swint req", - "int swint res", - "int lockup", - "interrupts" -}; - -static void -cs8900_stats (cs8900_device *cs) -{ - int i; - int max_label = 0; - int len; - unsigned long *value = (unsigned long*) &cs->eth_stats.rx_packets; - - cs->eth_stats.rx_missed_errors += - mem_pp_get_reg (cs, CS8900_PP_RxMISS) >> 6; - - cs->eth_stats.tx_collisions += - mem_pp_get_reg (cs, CS8900_PP_TxCol) >> 6; - - printf ("Network Driver Stats for CS8900 :\n"); - - for (i = 0; i < (sizeof (eth_statistics_labels) / sizeof (const char *)); i++) - { - len = strlen (eth_statistics_labels[i]); - if (len > max_label) - max_label = len; - } - - max_label += 2; - - printf ("%*s - %10u %*s - %10u\n", - max_label, "rx ready len", cs->rx_ready_len, - max_label, "rx loaded len", cs->rx_loaded_len); - - for (i = 0; - i < (sizeof (eth_statistics_labels) / sizeof (const char *)); - i++) - { - printf ("%*s - %10lu", - max_label, eth_statistics_labels[i], value[i]); - - i++; - - if (i < (sizeof (eth_statistics_labels) / sizeof (const char *))) - printf (" %*s - %10lu", - max_label, eth_statistics_labels[i], value[i]); - printf ("\n"); - } - -#if CS8900_TRACE - - for (i = 0; i < cs->trace_in; i++) - { - printf ("%8ld.%03ld ", cs->trace_time[i] / 1000, cs->trace_time[i] % 1000); - - if (cs->trace_key[i] < sizeof (cs8900_trace_labels) / sizeof (char*)) - printf ("%s : ", cs8900_trace_labels[cs->trace_key[i]]); - else - printf ("unknown trace key, %d : ", cs->trace_key[i]); - - if (cs->trace_key[i] == CS8900_T_INT) - { - printf ("0x%04lx ", cs->trace_var[i]); - if (cs->trace_var[i] == 0) - printf ("end"); - else - { - switch (cs->trace_var[i] & 0x1f) - { - case 0x04: - printf ("rx event"); - break; - - case 0x08: - printf ("tx event"); - break; - - case 0x0c: - printf ("buffer event"); - break; - - case 0x10: - printf ("rx missed"); - break; - - case 0x12: - printf ("tx collisions"); - break; - - case 0x1f: - printf ("tx request"); - break; - - case 0x1e: - printf ("tx wait 4 tx"); - break; - - case 0x1d: - printf ("tx already active"); - break; - - default: - printf ("unknown event"); - break; - } - } - } - else - printf ("0x%08lx", cs->trace_var[i]); - - printf ("\n"); - } - - cs->trace_in = 0; - -#endif -} - -static void -cs8900_init (void *arg) -{ - cs8900_device *cs = arg; - struct ifnet *ifp = &cs->arpcom.ac_if; - - if (cs->rx_task == 0) - { - - /* - * Set up the hardware. - */ - - cs8900_hardware_init (cs); - - /* - * Start driver task. We have only one task. - */ - - cs->rx_task = rtems_bsdnet_newproc ("CSr0", 4096, cs8900_rx_task, cs); - cs->tx_task = rtems_bsdnet_newproc ("CSt0", 4096, cs8900_tx_task, cs); - } - -#ifdef todo - /* - * Set flags appropriately - */ - if (ifp->if_flags & IFF_PROMISC) - else -#endif - - /* - * Tell the world that we're running. - */ - - ifp->if_flags |= IFF_RUNNING; - - /* - * Set the Line Control to bring the receive and transmitter online. - */ - - mem_pp_bit_set_reg (cs, CS8900_PP_LineCFG, - CS8900_LINE_CTRL_RX_ON | - CS8900_LINE_CTRL_TX_ON); - - mem_pp_bit_set_reg (cs, CS8900_PP_BusCTL, - CS8900_BUS_CTRL_ENABLE_INT); -} - -static int -cs8900_ioctl (struct ifnet *ifp, ioctl_command_t cmd, caddr_t data) -{ - cs8900_device *cs = ifp->if_softc; - int error = 0; - - switch (cmd) - { - case SIOCGIFADDR: - case SIOCSIFADDR: - - error = ether_ioctl (ifp, cmd, data); - break; - - case SIOCSIFFLAGS: - - switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) - { - case IFF_RUNNING: - - cs8900_stop (cs); - break; - - case IFF_UP: - - cs8900_init (cs); - break; - - case IFF_UP | IFF_RUNNING: - - cs8900_stop (cs); - cs8900_init (cs); - break; - - default: - break; - } - break; - - case SIO_RTEMS_SHOW_STATS: - - cs8900_stats (cs); - break; - - /* FIXME: Multicast commands must be added here. */ - - default: - error = EINVAL; - break; - } - - return error; -} - -int -cs8900_driver_attach (struct rtems_bsdnet_ifconfig *config, int attaching) -{ - cs8900_device *cs; - struct ifnet *ifp; - int mtu; - int unit; - char *name; - - /* - * Parse driver name - */ - - if ((unit = rtems_bsdnet_parse_driver_name (config, &name)) < 0) - return 0; - - cs = config->drv_ctrl; - cs->dev = unit; - ifp = &cs->arpcom.ac_if; - - if (attaching) - { - if (ifp->if_softc) - { - printf ("Driver `%s' already in use.\n", config->name); - return 0; - } - - /* - * Process options - */ - - if (config->hardware_address) - memcpy (cs->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); - else - cs8900_get_mac_addr (cs, cs->arpcom.ac_enaddr); - - if (config->mtu) - mtu = config->mtu; - else - mtu = ETHERMTU; - - cs->accept_bcast = !config->ignore_broadcast; - - /* - * Set up network interface values. - */ - - ifp->if_softc = cs; - ifp->if_unit = unit; - ifp->if_name = name; - ifp->if_mtu = mtu; - ifp->if_init = cs8900_init; - ifp->if_ioctl = cs8900_ioctl; - ifp->if_start = cs8900_start; - ifp->if_output = ether_output; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; - - if (ifp->if_snd.ifq_maxlen == 0) - ifp->if_snd.ifq_maxlen = ifqmaxlen; - - /* - * Attach the interface to the stack. - */ - - if_attach (ifp); - ether_ifattach (ifp); - } - else - { - if (!ifp->if_softc) - { - printf ("Driver `%s' not found.\n", config->name); - return 0; - } - - cs8900_stop (cs); - cs8900_detach_interrupt (cs); - } - - return 1; -} diff --git a/bsps/shared/net/cs8900.c.bsp b/bsps/shared/net/cs8900.c.bsp deleted file mode 100644 index 7b7374a0f2..0000000000 --- a/bsps/shared/net/cs8900.c.bsp +++ /dev/null @@ -1,510 +0,0 @@ -/* - * RTEMS CS8900 Driver Setup for the DIMM-PC/i386 made by Kontron. - * - * Port to the DIMM PC copyright (c) 2004 Angelo Fraietta - * This project has been assisted by the Commonwealth Government - * through the Australia Council, its arts funding and advisory body. - * - * Port performed by Chris Johns, Cybertec Pty Ltd, Jan 2004. - * Based on the Cybertec CS8900 driver setup for the SFP-101. - * - */ - -#define CS8900_VERBOSE 0 -#define HAVE_MRB_CS8900_DATA_BUS_SWAPPED 1 - -#include <bsp.h> - -#include <stdlib.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <arpa/inet.h> - -#include <rtems.h> -#include <rtems/monitor.h> -#include <rtems/rtems_bsdnet.h> -#include <irq.h> - -#include "cs8900.h" - -#include <net/route.h> - -/* - * Loopback interface. - */ - -extern int rtems_bsdnet_loopattach (struct rtems_bsdnet_ifconfig *, int); - -static struct rtems_bsdnet_ifconfig loopback_config = -{ - "lo0", /* name */ - rtems_bsdnet_loopattach, /* attach function */ - NULL, /* link to next interface */ - "127.0.0.1", /* IP address */ - "255.0.0.0", /* IP net mask */ -}; - -/* - * Network configuration - */ - -struct rtems_bsdnet_config rtems_bsdnet_config = -{ - &loopback_config, - NULL, - 20, /* Network task priority */ - 32 * 1024, /* Mbuf capacity */ - 96 * 1024, /* Mbuf cluster capacity */ -}; - - -static void cs8900_isr (); -static void cs8900_int_off (const rtems_irq_connect_data* unused); -static void cs8900_int_on (const rtems_irq_connect_data* unused); -static int cs8900_int_is_on (const rtems_irq_connect_data *irq); - -/** - * The device's data. - */ -static cs8900_device cs8900; -static rtems_irq_connect_data cs8900_irq = -{ - 0, - cs8900_isr, - cs8900_int_on, - cs8900_int_off, - cs8900_int_is_on -}; - -#if CS8900_VERBOSE -static int cs8900_io_verbose = 1; -#endif - -/** - * Device structure for attaching to the BSD stack. - */ -static struct rtems_bsdnet_ifconfig cs8900_ifconfig = -{ - "cs0", /* name */ - cs8900_driver_attach, /* attach funtion */ - NULL, /* next interface */ - NULL, /* ip address */ - NULL, /* ip netmask */ - NULL, /* hardware address */ - 0, /* ignore broadcast */ - 0, /* mtu */ - 0, /* rbuf count */ - 0, /* xbuf count */ - 0, /* port */ - 0, /* irno */ - 0, /* bpar */ - 0 /* drv ctrl */ -}; - - -/* - * Commands to register. - */ - -rtems_monitor_command_entry_t rtems_bsdnet_commands[] = -{ - { - "ifstats", - "Show the interface stats.\n", - 0, - (void*) rtems_bsdnet_show_if_stats, - 0, - 0, - }, - { - "ipstats", - "Show the IP stats.\n", - 0, - (void*) rtems_bsdnet_show_ip_stats, - 0, - 0, - }, - { - "routes", - "Show the inet routes.\n", - 0, - (void*) rtems_bsdnet_show_inet_routes, - 0, - 0, - }, - { - "mbufs", - "Show the mbuf stats.\n", - 0, - (void*) rtems_bsdnet_show_mbuf_stats, - 0, - 0, - }, - { - "icmp", - "Show the ICMP stats.\n", - 0, - (void*) rtems_bsdnet_show_icmp_stats, - 0, - 0, - }, - { - "udp", - "Show the UDP stats.\n", - 0, - (void*) rtems_bsdnet_show_udp_stats, - 0, - 0, - }, - { - "tcp", - "Show the TCP stats.\n", - 0, - (void*) rtems_bsdnet_show_tcp_stats, - 0, - 0, - } -}; - -static void -cs8900_isr () -{ - /* - * Note: we could have a high priority task here to call the - * drivers handler. The would lower the interrupt latancy - * we aother wise have. - */ - cs8900_interrupt (cs8900_irq.name, &cs8900); -} - -static void -cs8900_int_on (const rtems_irq_connect_data *unused) -{ -} - -static void -cs8900_int_off (const rtems_irq_connect_data *unused) -{ -} - -static int -cs8900_int_is_on (const rtems_irq_connect_data *irq) -{ - return BSP_irq_enabled_at_i8259s (irq->name); -} - -void cs8900_io_set_reg (cs8900_device *cs, unsigned short reg, unsigned short data) -{ -#if CS8900_VERBOSE - if (cs8900_io_verbose) - printk ("CS8900: io set reg=0x%04x, data=0x%04x\n", reg, data); -#endif - outport_word (cs->io_base + reg, data); -} - -unsigned short cs8900_io_get_reg (cs8900_device *cs, unsigned short reg) -{ - unsigned short data; - inport_word (cs->io_base + reg, data); -#if CS8900_VERBOSE - if (cs8900_io_verbose) - printk ("CS8900: io get reg=0x%04x, data=0x%04x\n", reg, data); -#endif - return data; -} - -void cs8900_mem_set_reg (cs8900_device *cs, unsigned long reg, unsigned short data) -{ - printk ("CS8900: mem_set_reg register access called. Only IO supported.\n"); - while (1); -} - -unsigned short cs8900_mem_get_reg (cs8900_device *cs, unsigned long reg) -{ - printk ("CS8900: mem_get_reg register access called. Only IO supported.\n"); - while (1); - return 0; -} - -void cs8900_put_data_block (cs8900_device *cs, int len, unsigned char *data) -{ - unsigned short *src = (unsigned short *) ((unsigned long) data); - - for (; len > 1; len -= 2) - outport_word (cs->io_base, *src++); - - if (len) - outport_word (cs->io_base, *src++); -} - -unsigned short cs8900_get_data_block (cs8900_device *cs, unsigned char *data) -{ - unsigned short *dst; - int cnt; - int len; - - /* - * Drop the Rx status first. - */ - inport_word (cs->io_base, len); - - /* - * Now the length. - */ - inport_word (cs->io_base, len); - - dst = (unsigned short *) ((unsigned long) data); - cnt = len >> 1; - - while (cnt--) - inport_word (cs->io_base, *dst++); - - if (len & 1) - inport_word (cs->io_base, *dst++); - - return len; -} - -void -cs8900_tx_load (cs8900_device *cs, struct mbuf *m) -{ - unsigned int len; - unsigned char *src = 0; - unsigned short *wsrc = 0; - unsigned char remainder = 0; - unsigned char word[2]; - - while (m) - { - /* - * We can get empty mbufs from the stack. - */ - - len = m->m_len; - src = mtod (m, unsigned char*); - - if (len) - { - if (remainder) - { -#if HAVE_MRB_CS8900_DATA_BUS_SWAPPED - word[1] = *src++; -#else - word[0] = *src++; -#endif - outport_word (cs->io_base, *((unsigned short*) (unsigned long) &word)); - len--; - remainder = 0; - } - - if (len & 1) - { - remainder = 1; - len--; - } - - wsrc = (unsigned short*) src; - - for (; len; len -= 2, src += 2) - outport_word (cs->io_base, *wsrc++); - - if (remainder) -#if HAVE_MRB_CS8900_DATA_BUS_SWAPPED - word[0] = *src++; -#else - word[1] = *src++; -#endif - } - - m = m->m_next; - } - - if (remainder) - { -#if HAVE_MRB_CS8900_DATA_BUS_SWAPPED - word[1] = *src++; -#else - word[0] = *src++; -#endif - outport_word (cs->io_base, *((unsigned short*) (unsigned long) &word)); - } -} - -void cs8900_attach_interrupt (cs8900_device *cs) -{ - BSP_install_rtems_irq_handler (&cs8900_irq); -} - -void cs8900_detach_interrupt (cs8900_device *cs) -{ - BSP_remove_rtems_irq_handler (&cs8900_irq); -} - -void -BSP_cs8900_attach (unsigned long io_base, unsigned long mem_base, int intrp, - const char* ip, const char* nm, const char* gw) -{ - cs8900_device *cs = &cs8900; - int flags; - struct sockaddr_in address; - struct sockaddr_in netmask; - struct sockaddr_in broadcast; - struct sockaddr_in gateway; - int cmd; - - printf ("cso: io=0x%0lx mem=0 irq=%d\n", io_base, intrp); - - memset (cs, 0, sizeof (cs8900)); - - cs->dev = 0; - cs->rx_queue_size = 30; - cs->io_base = io_base; - - if (mem_base) - printf ("cs8900: memory mode is currently not supported.\n"); - - cs->mem_base = 0; - - switch (intrp) - { - case 5: - cs->irq_level = 3; - break; - case 10: - cs->irq_level = 0; - break; - case 11: - cs->irq_level = 1; - break; - case 12: - cs->irq_level = 2; - break; - default: - printf ("cs8900: unsupported IRQ level\n"); - return; - } - - cs8900_irq.name = intrp; - - /* - * Get the MAC adress from the CS8900. - */ - - cs8900_get_mac_addr (cs, cs->mac_address); - - /* - * Setup the BSD interface configure structure. - */ - - cs8900_ifconfig.drv_ctrl = cs; - cs8900_ifconfig.hardware_address = cs->mac_address; - - printf ("CS8900 initialisation\n"); - - rtems_bsdnet_attach (&cs8900_ifconfig); - - /* - * Configure the interface using the boot configuration. - */ - - flags = IFF_UP; - if (rtems_bsdnet_ifconfig (cs8900_ifconfig.name, - SIOCSIFFLAGS, - &flags) < 0) - { - printf ("error: can't bring up %s: %s\n", - cs8900_ifconfig.name, strerror (errno)); - return; - } - - if (ip && strlen (ip) && nm && strlen (nm)) - { - printf ("%s: addr: %s netmask: %s gateway: %s\n", - cs8900_ifconfig.name, ip, nm, gw ? gw : "none"); - - memset (&netmask, '\0', sizeof netmask); - netmask.sin_len = sizeof netmask; - netmask.sin_family = AF_INET; - - if (!inet_aton (nm, &netmask.sin_addr)) - { - printf ("error: cannot parse the network mask: %s\n", nm); - return; - } - - memset (&address, '\0', sizeof address); - address.sin_len = sizeof address; - address.sin_family = AF_INET; - - if (!inet_aton (ip, &address.sin_addr)) - { - printf ("error: cannot parse the ip address: %s\n", ip); - return; - } - - if (rtems_bsdnet_ifconfig (cs8900_ifconfig.name, - SIOCSIFNETMASK, - &netmask) < 0) - { - printf ("error: can't set %s netmask: %s\n", - cs8900_ifconfig.name, strerror (errno)); - return; - } - - if (rtems_bsdnet_ifconfig (cs8900_ifconfig.name, - SIOCSIFADDR, - &address) < 0) - { - printf ("error: can't set %s address: %s\n", - cs8900_ifconfig.name, strerror (errno)); - return; - } - - memset (&broadcast, '\0', sizeof broadcast); - broadcast.sin_len = sizeof broadcast; - broadcast.sin_family = AF_INET; - broadcast.sin_addr.s_addr = - (address.sin_addr.s_addr & netmask.sin_addr.s_addr) | ~netmask.sin_addr.s_addr; - - if (rtems_bsdnet_ifconfig (cs8900_ifconfig.name, - SIOCSIFBRDADDR, - &broadcast) < 0) - { - printf ("error: can't set %s broadcast address: %s\n", - cs8900_ifconfig.name, strerror (errno)); - return; - } - - if (gw && strlen (gw)) - { - address.sin_addr.s_addr = INADDR_ANY; - netmask.sin_addr.s_addr = INADDR_ANY; - memset (&gateway, '\0', sizeof gateway); - gateway.sin_len = sizeof gateway; - gateway.sin_family = AF_INET; - - if (!inet_aton (gw, &gateway.sin_addr)) - printf ("warning: cannot parse the gateway address: %s\n", ip); - else - { - if (rtems_bsdnet_rtrequest (RTM_ADD, - (struct sockaddr *) &address, - (struct sockaddr *) &gateway, - (struct sockaddr *) &netmask, - (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL) < 0) - printf ("error: can't set default route: %s\n", strerror (errno)); - } - } - } - else - { - rtems_bsdnet_do_bootp_and_rootfs (); - } - - for (cmd = 0; - cmd < sizeof (rtems_bsdnet_commands) / sizeof (rtems_monitor_command_entry_t); - cmd++) - rtems_monitor_insert_cmd (&rtems_bsdnet_commands[cmd]); -} |