source: rtems/c/src/lib/libbsp/powerpc/beatnik/network/porting/if_xxx_rtems.c @ 0f5c805d

4.10
Last change on this file since 0f5c805d was 0f5c805d, checked in by Ralf Corsepius <ralf.corsepius@…>, on 01/27/11 at 04:44:23

2011-01-27 Ralf Corsépius <ralf.corsepius@…>

  • Makefile.am: Remove build_date.c.
  • startup/bspstart.c: Remove BSP_build_date.
  • network/porting/README, network/porting/if_xxx_rtems.c, startup/bspstart.c: Remove CVS artefacts.
  • Property mode set to 100644
File size: 11.5 KB
Line 
1/* $Id$ */
2#include <rtemscompat.h>
3
4/* Template for driver task, setup and attach routines. To be instantiated
5 * by defining the relevant symbols in header files.
6 */
7
8/* Copyright: Till Straumann <strauman@slac.stanford.edu>, 2005;
9 * License:   see LICENSE file.
10 */
11
12#include <rtems/irq.h>
13
14#include <stdio.h>
15#include <string.h>
16#include <inttypes.h>
17
18#include <sys/cdefs.h>
19
20#include <sys/param.h>
21#include <sys/systm.h>
22#include <sys/kernel.h>
23#include <sys/socket.h>
24#include <sys/sockio.h>
25
26#include <net/if.h>
27#include <net/if_arp.h>
28
29#include <netinet/in.h>
30#include <netinet/if_ether.h>
31#include <arpa/inet.h>
32
33#include <net/if_media.h>
34
35#ifdef IF_REG_HEADER
36#include IF_REG_HEADER
37#endif
38#ifdef IF_VAR_HEADER
39#include IF_VAR_HEADER
40#endif
41
42#include <rtemscompat1.h>
43
44#define EX_EVENT RTEMS_EVENT_1
45#undef  IRQ_AT_8259
46
47NETDEV_DECL = { /*[0]:*/{ /* softc: */ { /* arpcom: */{ /* ac_if: */ { 0 }}}}};
48
49static void net_daemon(void *arg);
50
51#ifdef HAVE_LIBBSPEXT
52#include <bsp/bspExt.h>
53static void the_net_isr(void *);
54#else
55static void noop(const rtems_irq_connect_data *unused) {}
56static int  noop1(const rtems_irq_connect_data *unused) { return 0;}
57#if ISMINVERSION(4,6,99)
58static void the_net_isr(rtems_irq_hdl_param);
59#else
60static void the_net_isr();
61#if NETDRIVER_SLOTS > 1
62#error only one instance supported (stupid IRQ API)
63#else
64static struct NET_SOFTC *thesc;
65#endif
66#endif
67#endif
68
69#if defined(NETDRIVER_PCI)
70/* Public setup routine for PCI devices;
71 * TODO: currently doesn't work for subsystem vendor/id , i.e.
72 *       devices behind a standard PCI interface...
73 */
74int
75NET_EMBEMB(rtems_,NETDRIVER_PREFIX,_pci_setup)(int inst);
76#endif
77
78static unsigned
79NET_EMBEMB(,NETDRIVER_PREFIX,_net_driver_ticks_per_sec) = 0;
80
81/* other drivers may already have this created */
82extern unsigned net_driver_ticks_per_sec
83__attribute__((weak, alias(NET_STRSTR(NETDRIVER_PREFIX)"_net_driver_ticks_per_sec") ));
84
85#ifdef DEBUG_MODULAR
86net_drv_tbl_t * volatile METHODSPTR = 0;
87#endif
88
89
90int
91NET_EMBEMB(rtems_,NETDRIVER_PREFIX,_attach)
92        (struct rtems_bsdnet_ifconfig *config, int attaching)
93{
94        int error     = 0;
95        device_t dev = net_dev_get(config);
96        struct  NET_SOFTC *sc;
97        struct  ifnet     *ifp;
98#ifndef HAVE_LIBBSPEXT
99        rtems_irq_connect_data irq_data = {
100                                0,
101                                the_net_isr,
102#if ISMINVERSION(4,6,99)
103                                0,
104#endif
105                                noop,
106                                noop,
107                                noop1 };
108#endif
109
110        if ( !dev )
111                return 1;
112
113        if ( !dev->d_softc.NET_SOFTC_BHANDLE_FIELD ) {
114#if defined(NETDRIVER_PCI)
115                device_printf(dev,NETDRIVER" unit not configured; executing setup...");
116                /* setup should really be performed prior to attaching.
117                 * Wipe the device; setup and re-obtain the device...
118                 */
119                memset(dev,0,sizeof(*dev));
120                error = NET_EMBEMB(rtems_,NETDRIVER_PREFIX,_pci_setup)(-1);
121                /* re-obtain the device */
122                dev   = net_dev_get(config);
123                if ( !dev ) {
124                        printk("Unable to re-assign device structure???\n");
125                        return 1;
126                }
127                if (error <= 0) {
128                        device_printf(dev,NETDRIVER" FAILED; unable to attach interface, sorry\n");
129                        return 1;
130                }
131                device_printf(dev,"success\n");
132#else
133                device_printf(dev,NETDRIVER" unit not configured; use 'rtems_"NETDRIVER"_setup()'\n");
134                return 1;
135#endif
136        }
137
138        if ( !net_driver_ticks_per_sec )
139                rtems_clock_get( RTEMS_CLOCK_GET_TICKS_PER_SECOND, &net_driver_ticks_per_sec );
140
141        sc  = device_get_softc( dev );
142        ifp = &sc->arpcom.ac_if;
143
144#ifdef DEBUG_MODULAR
145        if (!METHODSPTR) {
146                device_printf(dev,NETDRIVER": method pointer not set\n");
147                return -1;
148        }
149#endif
150
151        if ( attaching ) {
152                if ( ifp->if_init ) {
153                        device_printf(dev,NETDRIVER" Driver already attached.\n");
154                        return -1;
155                }
156                if ( config->hardware_address ) {
157                        /* use configured MAC address */
158                        memcpy(sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
159                } else {
160#ifdef NET_READ_MAC_ADDR
161                        NET_READ_MAC_ADDR(sc);
162#endif
163                }
164                if ( METHODSPTR->n_attach(dev) ) {
165                        device_printf(dev,NETDRIVER"_attach() failed\n");
166                        return -1;
167                }
168        } else {
169                if ( !ifp->if_init ) {
170                        device_printf(dev,NETDRIVER" Driver not attached.\n");
171                        return -1;
172                }
173                if ( METHODSPTR->n_detach ) {
174                        if ( METHODSPTR->n_detach(dev) ) {
175                                device_printf(dev,NETDRIVER"_detach() failed\n");
176                                return -1;
177                        }
178                } else {
179                        device_printf(dev,NETDRIVER"_detach() not implemented\n");
180                        return -1;
181                }
182        }
183
184
185        if ( !sc->tid )
186                sc->tid = rtems_bsdnet_newproc(NETDRIVER"d", 4096, net_daemon, sc);
187
188        if (attaching) {
189#ifdef DEBUG
190                printf("Installing IRQ # %i\n",sc->irq_no);
191#endif
192#ifdef HAVE_LIBBSPEXT
193                if ( bspExtInstallSharedISR(sc->irq_no, the_net_isr, sc, 0) )
194#else
195                /* BSP dependent :-( */
196                irq_data.name   = sc->irq_no;
197#if ISMINVERSION(4,6,99)
198                irq_data.handle = (rtems_irq_hdl_param)sc;
199#else
200                thesc = sc;
201#endif
202                if ( ! BSP_install_rtems_irq_handler( &irq_data ) )
203#endif
204                {
205                        fprintf(stderr,NETDRIVER": unable to install ISR\n");
206                        error = -1;
207                }
208        } else {
209                if ( sc->irq_no ) {
210#ifdef DEBUG
211                printf("Removing IRQ # %i\n",sc->irq_no);
212#endif
213#ifdef HAVE_LIBBSPEXT
214                if (bspExtRemoveSharedISR(sc->irq_no, the_net_isr, sc))
215#else
216                /* BSP dependent :-( */
217                irq_data.name   = sc->irq_no;
218#if ISMINVERSION(4,6,99)
219                irq_data.handle = (rtems_irq_hdl_param)sc;
220#endif
221                if ( ! BSP_remove_rtems_irq_handler( &irq_data ) )
222#endif
223                {
224                        fprintf(stderr,NETDRIVER": unable to uninstall ISR\n");
225                        error = -1;
226                }
227                }
228        }
229        return error;
230}
231
232static void
233the_net_isr(
234#ifdef HAVE_LIBBSPEXT
235void *thesc
236#elif ISMINVERSION(4,6,99)
237rtems_irq_hdl_param thesc
238#endif
239)
240{
241struct NET_SOFTC *sc = thesc;
242
243        /* disable interrupts */
244        NET_DISABLE_IRQS(sc);
245
246        rtems_event_send( sc->tid, EX_EVENT );
247}
248
249static void net_daemon(void *arg)
250{
251struct NET_SOFTC *sc = arg;
252rtems_event_set evs;
253
254        for (;;) {
255                rtems_bsdnet_event_receive(
256                                EX_EVENT,
257                                RTEMS_WAIT | RTEMS_EVENT_ANY,
258                                RTEMS_NO_TIMEOUT,
259                                &evs);
260
261                METHODSPTR->n_intr(sc);
262
263                /* re-enable interrupts */
264                NET_ENABLE_IRQS(sc);
265        }
266}
267
268static struct NET_SOFTC *
269net_drv_check_unit(int unit)
270{
271        unit--;
272        if ( unit < 0 || unit >= NETDRIVER_SLOTS ) {
273                fprintf(stderr,"Invalid unit # %i (not in %i..%i)\n", unit+1, 1, NETDRIVER_SLOTS);
274                return 0;
275        }
276
277        if ( THEDEVS[unit].d_name ) {
278                fprintf(stderr,"Unit %i already set up\n", unit+1);
279                return 0;
280        }
281
282        memset( &THEDEVS[unit], 0, sizeof(THEDEVS[0]) );
283
284        return &THEDEVS[unit].d_softc;
285}
286
287struct rtems_bsdnet_ifconfig NET_EMBEMB(NETDRIVER_PREFIX,_dbg,_config) = {
288        NETDRIVER"1",
289        NET_EMBEMB(rtems_,NETDRIVER_PREFIX,_attach),
290        0
291};
292
293#ifdef DEBUG
294void
295NET_EMBEMB(rtems_,NETDRIVER_PREFIX,_bringup)(char *ipaddr)
296{
297short flags;
298struct sockaddr_in addr;
299char *mask;
300
301
302        if (!ipaddr) {
303                printf("Need an ip[/mask] argument (dot notation)\n");
304                return;
305        }
306
307        ipaddr = strdup(ipaddr);
308
309        if ( (mask = strchr(ipaddr,'/')) ) {
310                *mask++=0;
311        } else {
312                mask = "255.255.255.0";
313        }
314
315#if defined(NETDRIVER_PCI)
316        /* this fails if already setup */
317        NET_EMBEMB(rtems_,NETDRIVER_PREFIX,_pci_setup)(-1);
318#endif
319        rtems_bsdnet_attach(&NET_EMBEMB(NETDRIVER_PREFIX,_dbg,_config));
320
321        flags = IFF_UP /*| IFF_PROMISC*/;
322        if ( rtems_bsdnet_ifconfig(NETDRIVER"1",SIOCSIFFLAGS,&flags) < 0 ) {
323                printf("Can't bring '"NETDRIVER"1' up\n");
324                goto cleanup;
325        }
326        memset(&addr,0,sizeof(addr));
327        addr.sin_len = sizeof(addr);
328        addr.sin_family = AF_INET;
329        addr.sin_addr.s_addr = inet_addr(mask);
330        if ( rtems_bsdnet_ifconfig(NETDRIVER"1",SIOCSIFNETMASK,&addr) < 0 ) {
331                printf("Unable to set netmask on '"NETDRIVER"1'\n");
332                goto cleanup;
333        }
334        addr.sin_addr.s_addr = inet_addr(ipaddr);
335        if ( rtems_bsdnet_ifconfig(NETDRIVER"1",SIOCSIFADDR,&addr) < 0 ) {
336                printf("Unable to set address on '"NETDRIVER"1'\n");
337                goto cleanup;
338        }
339cleanup:
340        the_real_free (ipaddr);
341}
342
343int
344NET_EMBEMB(rtems_,NETDRIVER_PREFIX,_bringdown)()
345{
346short flags;
347        flags = 0;
348        if ( rtems_bsdnet_ifconfig(NETDRIVER"1",SIOCSIFFLAGS,&flags) < 0 ) {
349                printf("Can't bring '"NETDRIVER"1' down\n");
350                return -1;
351        }
352       
353        rtems_bsdnet_detach(&NET_EMBEMB(NETDRIVER_PREFIX,_dbg,_config));
354        return 0;
355}
356#endif
357
358
359#if defined(NETDRIVER_PCI) && !defined(NETDRIVER_OWN_SETUP)
360/* Public setup routine for PCI devices;
361 * TODO: currently doesn't work for subsystem vendor/id , i.e.
362 *       devices behind a standard PCI interface...
363 * passing 'inst' > only sets-up the 'inst'th card; passing
364 * 'inst' == 0 sets-up all matching cards.
365 */
366int
367NET_EMBEMB(rtems_,NETDRIVER_PREFIX,_pci_setup)(int inst)
368{
369unsigned b,d,f,i,isio,unit;
370rtemscompat_32_t base;
371unsigned short cmd,id;
372unsigned char  h;
373struct NET_SOFTC *sc;
374unsigned try[] = { PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, 0 };
375
376#ifdef DEBUG_MODULAR
377        if ( !METHODSPTR ) {
378                fprintf(stderr,NETDRIVER": Methods pointer not set\n");
379                return -1;
380        }
381#endif
382
383        /* 0 can be reached when looking for the desired instance */
384        if ( 0 == inst )
385                inst = -1;
386
387#ifdef HAVE_LIBBSPEXT
388        /* make sure it's initialized */
389        bspExtInit();
390#endif
391
392        /* scan PCI for supported devices */
393        for ( b=0, sc=0, unit=0; b<pci_bus_count(); b++ ) {
394                for ( d=0; d<PCI_MAX_DEVICES; d++ ) {
395                        pci_read_config_word(b,d,0,PCI_VENDOR_ID,&id);
396                        if ( 0xffff == id )
397                                        continue; /* empty slot */
398
399                        pci_read_config_byte(b,d,0,PCI_HEADER_TYPE,&h);
400                        h = h&0x80 ? PCI_MAX_FUNCTIONS : 1; /* multifunction device ? */
401
402                        for ( f=0;  f<h; f++ ) {
403                                if ( !sc && !(sc=net_drv_check_unit(unit+1))) {
404                                        fprintf(stderr,"Not enough driver slots; stop looking for more devices...\n");
405                                        return unit;
406                                }
407                                pci_read_config_word(b,d,f,PCI_VENDOR_ID,&id);
408                                if ( 0xffff == id )
409                                        continue; /* empty slot */
410
411                                pci_read_config_word(b,d,f,PCI_CLASS_DEVICE,&id);
412                                if ( PCI_CLASS_NETWORK_ETHERNET != id )
413                                        continue; /* only look at ethernet devices */
414                               
415                                sc->b = b;
416                                sc->d = d;
417                                sc->f = f;
418
419                                for ( i=0, base=0, isio=0; try[i]; i++ ) {
420                                        pci_read_config_dword(b,d,f,try[i],&base);
421                                        if ( base ) {
422                                                if ( (isio = (PCI_BASE_ADDRESS_SPACE_IO == (base & PCI_BASE_ADDRESS_SPACE )) ) ) {
423#ifdef NET_CHIP_PORT_IO
424                                                        base &= PCI_BASE_ADDRESS_IO_MASK;
425                                                        sc->NET_SOFTC_BHANDLE_FIELD = PCI_IO_2LOCAL(base,b);
426#ifdef DEBUG
427                                                        printf("Found PCI I/O Base 0x%08x\n", (unsigned)base);
428#endif
429#else
430                                                        base = 0;
431                                                        continue;
432#endif
433                                                } else {
434#ifdef NET_CHIP_MEM_IO
435                                                        base &= PCI_BASE_ADDRESS_MEM_MASK;
436                                                        sc->NET_SOFTC_BHANDLE_FIELD = PCI2LOCAL(base,b);
437#ifdef DEBUG
438                                                        printf("Found PCI MEM Base 0x%08x\n", (unsigned)base);
439#endif
440#else
441                                                        base = 0;
442                                                        continue;
443#endif
444                                                }
445                                        break;
446                                        }
447                                }
448                                if ( !base ) {
449#ifdef DEBUG
450                                        fprintf(stderr, NETDRIVER": (warning) Neither PCI base address 0 nor 1 are configured; skipping bus %i, slot %i, fn %i...\n",b,d,f);   
451#endif
452                                        continue;
453                                }
454
455                                if ( 0 == METHODSPTR->n_probe(&THEDEVS[unit]) && (inst < 0 || !--inst) ) {
456                                        pci_read_config_word(b,d,f,PCI_COMMAND,&cmd);
457                                        pci_write_config_word(b,d,f,PCI_COMMAND,
458                                                cmd | (isio ? PCI_COMMAND_IO : PCI_COMMAND_MEMORY) | PCI_COMMAND_MASTER );
459                                        pci_read_config_byte(b,d,f,PCI_INTERRUPT_LINE,&sc->irq_no);
460                                        printf(NETDRIVER": card found @PCI[%s] 0x%08x (local 0x%08x), IRQ %i\n",
461                                                (isio ? "io" : "mem"), (unsigned)base, sc->NET_SOFTC_BHANDLE_FIELD, sc->irq_no);
462
463                                        sc = 0; /* need to allocate a new slot */
464                                        unit++;
465
466                                        if ( 0 == inst ) {
467                                                /* found desired instance */
468                                                goto terminated;
469                                        }
470                                }
471                        }
472                }
473        }
474
475terminated:
476        return unit;
477}
478#else
479
480/* simple skeleton
481int
482NET_EMBEMB(rtems_,NETDRIVER_PREFIX,_setup)(
483        int             unit,
484        void    *base_addr,
485        int             irq_no)
486{
487struct NET_SOFTC *sc;
488        if ( !(sc=net_drv_check_unit(unit)) ) {
489                fprintf(stderr,"Bad unit number -- (not enought driver slots?)\n");
490                return 0;
491        }
492        sc->NET_SOFTC_BHANDLE_FIELD = base_addr;
493        if ( 0 == METHODSPTR->n_probe(&THEDEVS[unit-1]) ) {
494                sc->irq_no                                      = irq_no;
495                printf(NETDRIVER": Unit %i set up\n", unit);
496                return unit;
497        }
498        return 0;
499}
500*/
501
502#endif
Note: See TracBrowser for help on using the repository browser.