summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2004-03-14 01:28:34 +0000
committerChris Johns <chrisj@rtems.org>2004-03-14 01:28:34 +0000
commit528da1cb9f300fb0b685c91e06b18b817d6f7093 (patch)
tree10face68ded75215248d7dddef3975c820d9e2de
parentChanges made to support the DIMMPC. This is a pc396 target with IO port (diff)
downloadrtems-528da1cb9f300fb0b685c91e06b18b817d6f7093.tar.bz2
Updated the BSP example code.
-rw-r--r--c/src/libchip/network/cs8900.c.bsp587
-rw-r--r--c/src/libchip/network/cs8900.h.bsp41
2 files changed, 442 insertions, 186 deletions
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 <bsp.h>
- */
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <arpa/inet.h>
-#include <rtems/bspIo.h>
#include <rtems.h>
+#include <rtems/monitor.h>
+#include <rtems/rtems_bsdnet.h>
+#include <irq.h>
+
+#include "cs8900.h"
-#include <libchip/cs8900.h>
+#include <net/route.h>
/*
- * 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