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

5
Last change on this file since efb893f was efb893f, checked in by Sebastian Huber <sebastian.huber@…>, on 04/07/18 at 17:28:42

bsp/beatnik: Avoid RTEMS_RELLDFLAGS

Avoid extra CPPFLAGS.

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