source: rtems/bsps/shared/net/cs8900.c.bsp @ 82bc976

5
Last change on this file since 82bc976 was 27de4e1f, checked in by Sebastian Huber <sebastian.huber@…>, on 04/03/18 at 05:20:11

bsps: Move libchip to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

  • 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.