source: rtems/c/src/libchip/network/cs8900.c.bsp @ d0e2fa3

4.104.115
Last change on this file since d0e2fa3 was 528da1c, checked in by Chris Johns <chrisj@…>, on 03/14/04 at 01:28:34

Updated the BSP example code.

  • Property mode set to 100644
File size: 11.3 KB
Line 
1/*
2 * $Id$
3 *
4 * RTEMS CS8900 Driver Setup for the DIMM-PC/i386 made by Kontron.
5 *
6 * Port to the DIMM PC copyright (c) 2004 Angelo Fraietta
7 *   This project has been assisted by the Commonwealth Government
8 *   through the Australia Council, its arts funding and advisory body.
9 *
10 * Port performed by Chris Johns, Cybertec Pty Ltd, Jan 2004.
11 *  Based on the Cybertec CS8900 driver setup for the SFP-101.
12 *
13 */
14
15#define CS8900_VERBOSE 0
16#define HAVE_MRB_CS8900_DATA_BUS_SWAPPED 1
17
18#include <bsp.h>
19
20#include <stdlib.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
25#include <arpa/inet.h>
26
27#include <rtems.h>
28#include <rtems/monitor.h>
29#include <rtems/rtems_bsdnet.h>
30#include <irq.h>
31
32#include "cs8900.h"
33
34#include <net/route.h>
35
36/*
37 * Loopback interface.
38 */
39
40extern int rtems_bsdnet_loopattach (struct rtems_bsdnet_ifconfig *, int);
41
42static struct rtems_bsdnet_ifconfig loopback_config =
43{
44  "lo0",                    /* name */
45  rtems_bsdnet_loopattach,  /* attach function */
46  NULL,                     /* link to next interface */
47  "127.0.0.1",              /* IP address */
48  "255.0.0.0",              /* IP net mask */
49};
50
51/*
52 * Network configuration
53 */
54
55struct rtems_bsdnet_config rtems_bsdnet_config =
56{
57  &loopback_config,
58       NULL,
59         20,     /* Network task priority */
60  32 * 1024,     /* Mbuf capacity */
61  96 * 1024,     /* Mbuf cluster capacity */
62};
63
64
65static void cs8900_isr ();
66static void cs8900_int_off (const rtems_irq_connect_data* unused);
67static void cs8900_int_on (const rtems_irq_connect_data* unused);
68static int  cs8900_int_is_on (const rtems_irq_connect_data *irq);
69
70/**
71 * The device's data.
72 */
73static cs8900_device cs8900;
74static rtems_irq_connect_data cs8900_irq =
75{
76  0,
77  cs8900_isr,
78  cs8900_int_on,
79  cs8900_int_off,
80  cs8900_int_is_on
81};
82
83#if CS8900_VERBOSE
84static int cs8900_io_verbose = 1;
85#endif
86
87/**
88 * Device structure for attaching to the BSD stack.
89 */
90static struct rtems_bsdnet_ifconfig cs8900_ifconfig =
91{
92  "cs0",                       /* name */
93  cs8900_driver_attach,        /* attach funtion */
94  NULL,                        /* next interface */
95  NULL,                        /* ip address */
96  NULL,                        /* ip netmask */
97  NULL,                        /* hardware address */
98  0,                           /* ignore broadcast */
99  0,                           /* mtu */
100  0,                           /* rbuf count */
101  0,                           /* xbuf count */
102  0,                           /* port */
103  0,                           /* irno */
104  0,                           /* bpar */
105  0                            /* drv ctrl */
106};
107
108
109/*
110 * Commands to register.
111 */
112
113rtems_monitor_command_entry_t rtems_bsdnet_commands[] =
114{
115  {
116    "ifstats",
117    "Show the interface stats.\n",
118    0,
119    (void*) rtems_bsdnet_show_if_stats,
120    0,
121    0,
122  },
123  {
124    "ipstats",
125    "Show the IP stats.\n",
126    0,
127    (void*) rtems_bsdnet_show_ip_stats,
128    0,
129    0,
130  },
131  {
132    "routes",
133    "Show the inet routes.\n",
134    0,
135    (void*) rtems_bsdnet_show_inet_routes,
136    0,
137    0,
138  },
139  {
140    "mbufs",
141    "Show the mbuf stats.\n",
142    0,
143    (void*) rtems_bsdnet_show_mbuf_stats,
144    0,
145    0,
146  },
147  {
148    "icmp",
149    "Show the ICMP stats.\n",
150    0,
151    (void*) rtems_bsdnet_show_icmp_stats,
152    0,
153    0,
154  },
155  {
156    "udp",
157    "Show the UDP stats.\n",
158    0,
159    (void*) rtems_bsdnet_show_udp_stats,
160    0,
161    0,
162  },
163  {
164    "tcp",
165    "Show the TCP stats.\n",
166    0,
167    (void*) rtems_bsdnet_show_tcp_stats,
168    0,
169    0,
170  }
171};
172
173static void
174cs8900_isr ()
175{
176  /*
177   * Note: we could have a high priority task here to call the
178   *       drivers handler. The would lower the interrupt latancy
179   *       we aother wise have.
180   */
181  cs8900_interrupt (cs8900_irq.name, &cs8900);
182}
183
184static void
185cs8900_int_on (const rtems_irq_connect_data *unused)
186{
187}
188
189static void
190cs8900_int_off (const rtems_irq_connect_data *unused)
191{
192}
193
194static int
195cs8900_int_is_on (const rtems_irq_connect_data *irq)
196{
197  return BSP_irq_enabled_at_i8259s (irq->name);
198}
199
200void cs8900_io_set_reg (cs8900_device *cs, unsigned short reg, unsigned short data)
201{
202#if CS8900_VERBOSE
203  if (cs8900_io_verbose)
204    printk ("CS8900: io set reg=0x%04x, data=0x%04x\n", reg, data);
205#endif
206  outport_word (cs->io_base + reg, data);
207}
208
209unsigned short cs8900_io_get_reg (cs8900_device *cs, unsigned short reg)
210{
211  unsigned short data;
212  inport_word (cs->io_base + reg, data);
213#if CS8900_VERBOSE
214  if (cs8900_io_verbose)
215    printk ("CS8900: io get reg=0x%04x, data=0x%04x\n", reg, data);
216#endif
217  return data;
218}
219
220void cs8900_mem_set_reg (cs8900_device *cs, unsigned long reg, unsigned short data)
221{
222  printk ("CS8900: mem_set_reg register access called. Only IO supported.\n");
223  while (1);
224}
225
226unsigned short cs8900_mem_get_reg (cs8900_device *cs, unsigned long reg)
227{
228  printk ("CS8900: mem_get_reg register access called. Only IO supported.\n");
229  while (1);
230  return 0;
231}
232
233void cs8900_put_data_block (cs8900_device *cs, int len, unsigned char *data)
234{
235  unsigned short *src = (unsigned short *) ((unsigned long) data);
236
237  for (; len > 1; len -= 2)
238    outport_word (cs->io_base, *src++);
239
240  if (len)
241    outport_word (cs->io_base, *src++);
242}
243
244unsigned short cs8900_get_data_block (cs8900_device *cs, unsigned char *data)
245{
246  unsigned short *dst;
247  int             cnt;
248  int             len;
249
250  /*
251   * Drop the Rx status first.
252   */
253  inport_word (cs->io_base, len);
254
255  /*
256   * Now the length.
257   */
258  inport_word (cs->io_base, len);
259
260  dst = (unsigned short *) ((unsigned long) data);
261  cnt = len >> 1;
262
263  while (cnt--)
264    inport_word (cs->io_base, *dst++);
265
266  if (len & 1)
267    inport_word (cs->io_base, *dst++);
268
269  return len;
270}
271
272void
273cs8900_tx_load (cs8900_device *cs, struct mbuf *m)
274{
275  unsigned int   len;
276  unsigned char  *src = 0;
277  unsigned short *wsrc = 0;
278  unsigned char  remainder = 0;
279  unsigned char  word[2];
280
281  while (m)
282  {
283    /*
284     * We can get empty mbufs from the stack.
285     */
286
287    len = m->m_len;
288    src = mtod (m, unsigned char*);
289
290    if (len)
291    {
292      if (remainder)
293      {
294#if HAVE_MRB_CS8900_DATA_BUS_SWAPPED
295        word[1] = *src++;
296#else
297        word[0] = *src++;
298#endif
299        outport_word (cs->io_base, *((unsigned short*) (unsigned long) &word));
300        len--;
301        remainder = 0;
302      }
303
304      if (len & 1)
305      {
306        remainder = 1;
307        len--;
308      }
309
310      wsrc = (unsigned short*) src;
311
312      for (; len; len -= 2, src += 2)
313        outport_word (cs->io_base, *wsrc++);
314
315      if (remainder)
316#if HAVE_MRB_CS8900_DATA_BUS_SWAPPED
317       word[0] = *src++;
318#else
319       word[1] = *src++;
320#endif
321    }
322
323    m = m->m_next;
324  }
325
326  if (remainder)
327  {
328#if HAVE_MRB_CS8900_DATA_BUS_SWAPPED
329    word[1] = *src++;
330#else
331    word[0] = *src++;
332#endif
333    outport_word (cs->io_base, *((unsigned short*) (unsigned long) &word));
334  }
335}
336
337void cs8900_attach_interrupt (cs8900_device *cs)
338{
339  BSP_install_rtems_irq_handler (&cs8900_irq);
340}
341
342void cs8900_detach_interrupt (cs8900_device *cs)
343{
344  BSP_remove_rtems_irq_handler (&cs8900_irq);
345}
346
347void
348BSP_cs8900_attach (unsigned long io_base, unsigned long mem_base, int intrp,
349                   const char* ip, const char* nm, const char* gw)
350{
351  cs8900_device      *cs = &cs8900;
352  int                flags;
353  struct sockaddr_in address;
354  struct sockaddr_in netmask;
355  struct sockaddr_in broadcast;
356  struct sockaddr_in gateway;
357  int                cmd;
358
359  printf ("cso: io=0x%0lx mem=0 irq=%d\n", io_base, intrp);
360 
361  memset (cs, 0, sizeof (cs8900));
362
363  cs->dev = 0;
364  cs->rx_queue_size = 30;
365  cs->io_base = io_base;
366
367  if (mem_base)
368    printf ("cs8900: memory mode is currently not supported.\n");
369 
370  cs->mem_base = 0;
371 
372  switch (intrp)
373  {
374    case 5:
375      cs->irq_level = 3;
376      break;
377    case 10:
378      cs->irq_level = 0;
379      break;
380    case 11:
381      cs->irq_level = 1;
382      break;
383    case 12:
384      cs->irq_level = 2;
385      break;
386    default:
387      printf ("cs8900: unsupported IRQ level\n");
388      return;
389  }
390
391  cs8900_irq.name = intrp;
392 
393  /*
394   * Get the MAC adress from the CS8900.
395   */
396
397  cs8900_get_mac_addr (cs, cs->mac_address);
398
399  /*
400   * Setup the BSD interface configure structure.
401   */
402
403  cs8900_ifconfig.drv_ctrl = cs;
404  cs8900_ifconfig.hardware_address = cs->mac_address;
405
406  printf ("CS8900 initialisation\n");
407
408  rtems_bsdnet_attach (&cs8900_ifconfig);
409
410  /*
411   * Configure the interface using the boot configuration.
412   */
413
414  flags = IFF_UP;
415  if (rtems_bsdnet_ifconfig (cs8900_ifconfig.name,
416                             SIOCSIFFLAGS,
417                             &flags) < 0)
418  {
419    printf ("error: can't bring up %s: %s\n",
420            cs8900_ifconfig.name, strerror (errno));
421    return;
422  }
423
424  if (ip && strlen (ip) && nm && strlen (nm))
425  {
426    printf ("%s: addr: %s  netmask: %s  gateway: %s\n",
427            cs8900_ifconfig.name, ip, nm, gw ? gw : "none");
428
429    memset (&netmask, '\0', sizeof netmask);
430    netmask.sin_len    = sizeof netmask;
431    netmask.sin_family = AF_INET;
432
433    if (!inet_aton (nm, &netmask.sin_addr))
434    {
435      printf ("error: cannot parse the network mask: %s\n", nm);
436      return;
437    }
438
439    memset (&address, '\0', sizeof address);
440    address.sin_len    = sizeof address;
441    address.sin_family = AF_INET;
442
443    if (!inet_aton (ip, &address.sin_addr))
444    {
445      printf ("error: cannot parse the ip address: %s\n", ip);
446      return;
447    }
448
449    if (rtems_bsdnet_ifconfig (cs8900_ifconfig.name,
450                               SIOCSIFNETMASK,
451                               &netmask) < 0)
452    {
453      printf ("error: can't set %s netmask: %s\n",
454              cs8900_ifconfig.name, strerror (errno));
455      return;
456    }
457
458    if (rtems_bsdnet_ifconfig (cs8900_ifconfig.name,
459                               SIOCSIFADDR,
460                               &address) < 0)
461    {
462      printf ("error: can't set %s address: %s\n",
463              cs8900_ifconfig.name, strerror (errno));
464      return;
465    }
466
467    memset (&broadcast, '\0', sizeof broadcast);
468    broadcast.sin_len         = sizeof broadcast;
469    broadcast.sin_family      = AF_INET;
470    broadcast.sin_addr.s_addr =
471      (address.sin_addr.s_addr & netmask.sin_addr.s_addr) | ~netmask.sin_addr.s_addr;
472
473    if (rtems_bsdnet_ifconfig (cs8900_ifconfig.name,
474                               SIOCSIFBRDADDR,
475                               &broadcast) < 0)
476    {
477      printf ("error: can't set %s broadcast address: %s\n",
478              cs8900_ifconfig.name, strerror (errno));
479      return;
480    }
481
482    if (gw && strlen (gw))
483    {
484      address.sin_addr.s_addr = INADDR_ANY;
485      netmask.sin_addr.s_addr = INADDR_ANY;
486      memset (&gateway, '\0', sizeof gateway);
487      gateway.sin_len         = sizeof gateway;
488      gateway.sin_family      = AF_INET;
489
490      if (!inet_aton (gw, &gateway.sin_addr))
491        printf ("warning: cannot parse the gateway address: %s\n", ip);
492      else
493      {
494        if (rtems_bsdnet_rtrequest (RTM_ADD,
495                                    (struct sockaddr *) &address,
496                                    (struct sockaddr *) &gateway,
497                                    (struct sockaddr *) &netmask,
498                                    (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL) < 0)
499          printf ("error: can't set default route: %s\n", strerror (errno));
500      }
501    }
502  }
503  else
504  {
505    rtems_bsdnet_do_bootp_and_rootfs ();
506  }
507
508  for (cmd = 0;
509       cmd < sizeof (rtems_bsdnet_commands) / sizeof (rtems_monitor_command_entry_t);
510       cmd++)
511    rtems_monitor_insert_cmd (&rtems_bsdnet_commands[cmd]);
512}
Note: See TracBrowser for help on using the repository browser.