From 528da1cb9f300fb0b685c91e06b18b817d6f7093 Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Sun, 14 Mar 2004 01:28:34 +0000 Subject: Updated the BSP example code. --- c/src/libchip/network/cs8900.c.bsp | 587 +++++++++++++++++++++++++------------ c/src/libchip/network/cs8900.h.bsp | 41 +++ 2 files changed, 442 insertions(+), 186 deletions(-) create mode 100644 c/src/libchip/network/cs8900.h.bsp diff --git a/c/src/libchip/network/cs8900.c.bsp b/c/src/libchip/network/cs8900.c.bsp index 38935539d8..a31d1b0180 100644 --- a/c/src/libchip/network/cs8900.c.bsp +++ b/c/src/libchip/network/cs8900.c.bsp @@ -1,217 +1,283 @@ /* - ------------------------------------------------------------------------ - $Id$ - ------------------------------------------------------------------------ - - 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). + * $Id$ + * + * 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. + * + */ - 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. - - ------------------------------------------------------------------------ +#define CS8900_VERBOSE 0 +#define HAVE_MRB_CS8900_DATA_BUS_SWAPPED 1 - CS8900 net boot driver. +#include - */ +#include +#include +#include +#include + +#include -#include #include +#include +#include +#include + +#include "cs8900.h" -#include +#include /* - * Our local data. + * Loopback interface. */ -#ifdef CS8900_VERBOSE -static BOOLEAN cs8900_io_verbose; -#endif +extern int rtems_bsdnet_loopattach (struct rtems_bsdnet_ifconfig *, int); -static rtems_isr_void_entry old_handler[CS8900_DEVICES]; -static void *old_parameter[CS8900_DEVICES]; +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 */ +}; /* - * Tables of IO addresses and interrupt levels for each device attached. + * Network configuration */ -static const unsigned long ethernet_io_base[CS8900_DEVICES] = +struct rtems_bsdnet_config rtems_bsdnet_config = { - ETHERNET_BASE + &loopback_config, + NULL, + 20, /* Network task priority */ + 32 * 1024, /* Mbuf capacity */ + 96 * 1024, /* Mbuf cluster capacity */ }; -static const unsigned long ethernet_mem_base[CS8900_DEVICES] = -{ - ETHERNET_BASE + CS8900_MEMORY_BASE -}; -static const unsigned int ethernet_irq_level[CS8900_DEVICES] = +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 = { - ETHERNET_IRQ_LEVEL + 0, + cs8900_isr, + cs8900_int_on, + cs8900_int_off, + cs8900_int_is_on }; -static const unsigned int ethernet_irq_priority[CS8900_DEVICES] = +#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 = { - ETHERNET_IRQ_PRIORITY + "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 */ }; -static const unsigned int ethernet_irq_vector[CS8900_DEVICES] = + +/* + * Commands to register. + */ + +rtems_monitor_command_entry_t rtems_bsdnet_commands[] = { - ETHERNET_IRQ_VECTOR, + { + "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, + } }; -void cs8900_io_set_reg (int dev, unsigned short reg, unsigned short data) +static void +cs8900_isr () { -#ifdef CS8900_DATA_BUS_SWAPPED - data = (data >> 8) | (data << 8); -#endif - -#ifdef CS8900_VERBOSE - if (cs8900_io_verbose) - printf ("CS8900: io set reg=0x%04x, data=0x%04x\n", reg, data); -#endif - - WRITE_REGISTER_16 (ethernet_io_base[dev] + reg, data); + /* + * 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); } -unsigned short cs8900_io_get_reg (int dev, unsigned short reg) +static void +cs8900_int_on (const rtems_irq_connect_data *unused) { - unsigned long data; - - READ_REGISTER_16 (ethernet_io_base[dev] + reg, data); +} -#ifdef CS8900_DATA_BUS_SWAPPED - data = (data >> 8) | (data << 8); -#endif - -#ifdef CS8900_VERBOSE - if (cs8900_io_verbose) - printk ("CS8900: io get reg=0x%04x, data=0x%04x\n", reg, data); -#endif - - return data; +static void +cs8900_int_off (const rtems_irq_connect_data *unused) +{ } -void cs8900_mem_set_reg (int dev, unsigned long reg, unsigned short data) +static int +cs8900_int_is_on (const rtems_irq_connect_data *irq) { -#ifdef CS8900_DATA_BUS_SWAPPED - data = (data >> 8) | (data << 8); -#endif + return BSP_irq_enabled_at_i8259s (irq->name); +} -#ifdef CS8900_VERBOSE +void cs8900_io_set_reg (cs8900_device *cs, unsigned short reg, unsigned short data) +{ +#if CS8900_VERBOSE if (cs8900_io_verbose) - printk ("CS8900: mem set reg=0x%04x, data=0x%04x\n", reg, data); + printk ("CS8900: io set reg=0x%04x, data=0x%04x\n", reg, data); #endif - - WRITE_REGISTER_16 (ethernet_io_base[dev] + reg, data); + outport_word (cs->io_base + reg, data); } -unsigned short cs8900_mem_get_reg (int dev, unsigned long reg) +unsigned short cs8900_io_get_reg (cs8900_device *cs, unsigned short reg) { unsigned short data; - READ_REGISTER_16 (ethernet_io_base[dev] + reg, data); - -#ifdef CS8900_DATA_BUS_SWAPPED - data = (data >> 8) | (data << 8); -#endif - -#ifdef CS8900_VERBOSE + inport_word (cs->io_base + reg, data); +#if CS8900_VERBOSE if (cs8900_io_verbose) - printk ("CS8900: mem get reg=0x%04x, data=0x%04x\n", reg, data); + printk ("CS8900: io get reg=0x%04x, data=0x%04x\n", reg, data); #endif - return data; } -void cs8900_put_data_block (int dev, int len, unsigned char *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) { -#ifndef CS8900_DATA_BUS_SWAPPED - unsigned short swap_word; -#endif unsigned short *src = (unsigned short *) ((unsigned long) data); - unsigned short *dst = (unsigned short *) (ethernet_mem_base[dev] + CS8900_PP_TxFrameLoc); - while (len > 1) - { -#ifndef CS8900_DATA_BUS_SWAPPED - swap_word = *src++; - *dst++ = (swap_word >> 8) | (swap_word << 8); -#else - *dst++ = *src++; -#endif - len -= 2; - } + for (; len > 1; len -= 2) + outport_word (cs->io_base, *src++); if (len) - { -#ifndef CS8900_DATA_BUS_SWAPPED - swap_word = *src++; - *dst++ = (swap_word >> 8) | (swap_word << 8); -#else - *dst++ = *src++; -#endif - } + outport_word (cs->io_base, *src++); } -unsigned short cs8900_get_data_block (int dev, unsigned char *data) +unsigned short cs8900_get_data_block (cs8900_device *cs, unsigned char *data) { - unsigned short swap_word; - volatile unsigned short *src = (unsigned short *) (ethernet_mem_base[dev] + CS8900_PP_RxLength); - unsigned short *dst; - unsigned short len; - unsigned short rx_len; - unsigned short len_odd; - -#ifdef CS8900_DATA_BUS_SWAPPED - swap_word = *src++; - len = (swap_word >> 8) | (swap_word << 8); -#else - len = *src++; -#endif - + 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; - len_odd = len & 1; - rx_len = len & ~1; - - for (; rx_len; rx_len -= 2) - { -#ifndef CS8900_DATA_BUS_SWAPPED - swap_word = *src++; - *dst++ = (swap_word >> 8) | (swap_word << 8); -#else - *dst++ = *src++; -#endif - } + while (cnt--) + inport_word (cs->io_base, *dst++); - if (len_odd) - { -#ifndef CS8900_DATA_BUS_SWAPPED - swap_word = *src++; - *dst++ = (swap_word >> 8) | (swap_word << 8); -#else - *dst++ = *src++; -#endif - } + if (len & 1) + inport_word (cs->io_base, *dst++); return len; } void -cs8900_tx_load (int dev, struct mbuf *m) +cs8900_tx_load (cs8900_device *cs, struct mbuf *m) { - volatile unsigned short *dst = (unsigned short *) (ethernet_mem_base[dev] + CS8900_PP_TxFrameLoc); - unsigned int len; - unsigned char *src; - int remainder = 0; - unsigned char remainder_data = '\0'; - + unsigned int len; + unsigned char *src = 0; + unsigned short *wsrc = 0; + unsigned char remainder = 0; + unsigned char word[2]; + while (m) { /* @@ -225,11 +291,12 @@ cs8900_tx_load (int dev, struct mbuf *m) { if (remainder) { -#ifndef CS8900_DATA_BUS_SWAPPED - *dst++ = remainder_data | (*src++ << 8); +#if HAVE_MRB_CS8900_DATA_BUS_SWAPPED + word[1] = *src++; #else - *dst++ = *src++ | (remainder_data << 8); + word[0] = *src++; #endif + outport_word (cs->io_base, *((unsigned short*) (unsigned long) &word)); len--; remainder = 0; } @@ -239,59 +306,207 @@ cs8900_tx_load (int dev, struct mbuf *m) remainder = 1; len--; } - - for (; len; len -= 2) -#ifndef CS8900_DATA_BUS_SWAPPED - *dst++ = (*src++) | (*(++src) << 8); + + 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 - *dst++ = (*src++ << 8) | *(++src); + word[1] = *src++; #endif - - if (remainder) - remainder_data = *src++; } - + m = m->m_next; } if (remainder) { -#ifndef CS8900_DATA_BUS_SWAPPED - *dst = (unsigned short) remainder_data; +#if HAVE_MRB_CS8900_DATA_BUS_SWAPPED + word[1] = *src++; #else - *dst = (unsigned short) (remainder_data << 8); + word[0] = *src++; #endif + outport_word (cs->io_base, *((unsigned short*) (unsigned long) &word)); } } -void cs8900_attach_interrupt (int dev, cs8900_device *cs) +void cs8900_attach_interrupt (cs8900_device *cs) { - rtems_interrupt_catch_with_void (cs8900_interrupt, - ethernet_irq_vector[dev], - &old_handler[dev], - cs, - &old_parameter[dev]); - - CF_SIM_WRITE_ICR (CF_BASE, - ethernet_irq_level[dev], - CF_SIM_ICR_AVEC_AUTO, - ethernet_irq_level[dev], - ethernet_irq_priority[dev]); - CF_SIM_IMR_ENABLE (CF_BASE, 1 << ethernet_irq_level[dev]); + BSP_install_rtems_irq_handler (&cs8900_irq); } -void cs8900_detach_interrupt (int dev) +void cs8900_detach_interrupt (cs8900_device *cs) { - CF_SIM_IMR_DISABLE (CF_BASE, 1 << ethernet_irq_level[dev]); - - rtems_interrupt_catch_with_void (old_handler, - ethernet_irq_vector[dev], - NULL, - old_parameter[dev], - NULL); + BSP_remove_rtems_irq_handler (&cs8900_irq); } -void cs8900_get_mac_addr (int dev, unsigned char *mac_address) +void +BSP_cs8900_attach (unsigned long io_base, unsigned long mem_base, int intrp, + const char* ip, const char* nm, const char* gw) { - memcpy (mac_address, rct_get_mac_address (dev), 6); + 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]); } diff --git a/c/src/libchip/network/cs8900.h.bsp b/c/src/libchip/network/cs8900.h.bsp new file mode 100644 index 0000000000..a0792fdf97 --- /dev/null +++ b/c/src/libchip/network/cs8900.h.bsp @@ -0,0 +1,41 @@ +/* + * $Id$ + * + * 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. + * + */ + +#if !defined (__BSP_CS8900_H__) +#define __BSP_CS8900_H__ + +/** + * BSP CS8900 Device initialisation and interface attach. + * + * @param io_base The I/O base address of the device. + * + * @param mem_base The memory base address. Currently not used. + * + * @param intrp The ISA bus IRQ. These are currently limited to + * 5, 10, 11, and 12 as documented in the CS8900 + * manual. + * + * @param ip IP address in ASCII. For example 10.10.10.10. If the + * pointer is a NULL (0) the interface will BOOTP. + * + * @param nm Network Mask in ASCII. For example 10.10.10.255. + * + * @param gw Address of the gateway machine. For example + * 10.10.10.1. + */ + +void BSP_cs8900_attach (unsigned long io_base, unsigned long mem_base, int intrp, + const char* ip, const char* nm, const char* gw); + +#endif -- cgit v1.2.3