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

4.115
Last change on this file since 40a24661 was 65c6425, checked in by Joel Sherrill <joel.sherrill@…>, on 05/03/12 at 17:24:46

Remove CVS Id Strings (manual edits after script)

These modifications were required by hand after running the script.
In some cases, the file names did not match patterns. In others,
the format of the file did not match any common patterns.

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