source: rtems/c/src/lib/libbsp/powerpc/beatnik/network/support/bsp_attach.c @ b7a6d23a

4.104.11
Last change on this file since b7a6d23a was b7a6d23a, checked in by Till Straumann <strauman@…>, on Dec 3, 2009 at 4:56:50 PM
  • importing 'beatnik' BSP from SLAC repository.
  • Property mode set to 100644
File size: 12.7 KB
Line 
1/* $Id$ */
2
3/* BSP specific wrapper for rtems_bsdnet_attach(). This wrapper
4 * dispatches to the correct driver attach routine depending on
5 * the board type, boot parameters, link status etc.
6 *
7 * Also, it performs board-specific setup of driver parameters
8 * (such as ethernet address, base addresses and the like)
9 */
10
11/*
12 * Authorship
13 * ----------
14 * This software ('beatnik' RTEMS BSP for MVME6100 and MVME5500) was
15 *     created by Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
16 *         Stanford Linear Accelerator Center, Stanford University.
17 *
18 * Acknowledgement of sponsorship
19 * ------------------------------
20 * The 'beatnik' BSP was produced by
21 *     the Stanford Linear Accelerator Center, Stanford University,
22 *         under Contract DE-AC03-76SFO0515 with the Department of Energy.
23 *
24 * Government disclaimer of liability
25 * ----------------------------------
26 * Neither the United States nor the United States Department of Energy,
27 * nor any of their employees, makes any warranty, express or implied, or
28 * assumes any legal liability or responsibility for the accuracy,
29 * completeness, or usefulness of any data, apparatus, product, or process
30 * disclosed, or represents that its use would not infringe privately owned
31 * rights.
32 *
33 * Stanford disclaimer of liability
34 * --------------------------------
35 * Stanford University makes no representations or warranties, express or
36 * implied, nor assumes any liability for the use of this software.
37 *
38 * Stanford disclaimer of copyright
39 * --------------------------------
40 * Stanford University, owner of the copyright, hereby disclaims its
41 * copyright and all other rights in this software.  Hence, anyone may
42 * freely use it for any purpose without restriction. 
43 *
44 * Maintenance of notices
45 * ----------------------
46 * In the interest of clarity regarding the origin and status of this
47 * SLAC software, this and all the preceding Stanford University notices
48 * are to remain affixed to any copy or derivative of this software made
49 * or distributed by the recipient and are to be affixed to any copy of
50 * software made or distributed by the recipient that contains a copy or
51 * derivative of this software.
52 *
53 * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
54 */ 
55
56#include <rtems.h>
57#include <rtems/rtems_bsdnet.h>
58
59#include <bsp.h>
60#include <bsp/irq.h>
61#include <bsp/pci.h>
62
63#include <bsp/early_enet_link_status.h>
64
65#include <bsp/if_mve_pub.h>
66#include <bsp/if_gfe_pub.h>
67#include <bsp/if_em_pub.h>
68
69#include <stdio.h>
70#include <string.h>
71#include <assert.h>
72
73#define IS_6100()               (MVME6100 == BSP_getBoardType())
74#define IS_5500()               (MVME5500 == BSP_getBoardType())
75
76static int bsp_gfe_attach(struct rtems_bsdnet_ifconfig *, int);
77static int mvme5500_em_attach (struct rtems_bsdnet_ifconfig *, int);
78static int mvme5500_em_find_onboard_unit(void);
79
80char BSP_auto_network_driver_name[20] = {0,};
81
82static BSP_NetIFDescRec mvme6100_netifs[] = {
83        {
84                name:                   "mve1",
85                description:    "MV64360 built-in 10/100/1000 Ethernet 1",
86                attach_fn:              rtems_mve_attach
87        },
88        {
89                name:                   "mve2",
90                description:    "MV64360 built-in 10/100/1000 Ethernet 2",
91                attach_fn:              rtems_mve_attach
92        },
93        {
94                name:                   0,
95        }
96};
97
98static BSP_NetIFDescRec mvme5500_netifs[] = {
99        {
100                name:                   "em1",
101                description:    "Intel 82544 on-board 10/100/1000 Ethernet (port 1)",
102                attach_fn:              mvme5500_em_attach,
103        },
104        {
105                name:                   "gfe1",
106                description:    "GT64260 built-in 10/100 Ethernet (port 2)",
107                attach_fn:              bsp_gfe_attach,
108        },
109        {
110                name:                   0,
111        }
112};
113
114
115/* wrap the 'gfe' and 'em' attach functions.
116 * RATIONALE: 'rtems_gfe_attach()' and 'rtems_em_attach()' are
117 *            *chip* specific functions. However, they require
118 *            some *board* specific parameter setup prior to
119 *            being attached which is what these wrappers do...
120 */
121
122static unsigned em_info[];
123
124static int scan4irqLine(int bus, int dev, int fn, void *uarg)
125{
126unsigned char  byte;
127unsigned short word;
128int            i;
129
130        /* count the number of 82544 we find */
131        pci_read_config_word(bus, dev, fn, PCI_VENDOR_ID, &word);
132        if ( 0x8086 != word )
133                return 0;
134
135        pci_read_config_word(bus, dev, fn, PCI_DEVICE_ID, &word);
136        for ( i = 0; em_info[i]; i++ ) {
137                if ( em_info[i] == word )
138                        break;
139        }
140
141        if ( !em_info[i] )
142                return 0;
143
144        /* found a candidate; bump unit number */
145        (*(int *)uarg)++;
146
147        pci_read_config_byte(bus, dev, fn, PCI_INTERRUPT_LINE, &byte);
148
149        /* On the mvme5500 the 82544 is hooked to GPP IRQ 20 */
150
151        return ( BSP_IRQ_GPP_0 + 20 == byte ) ? 1 : 0;
152}
153
154/* Setup only once */
155static void
156onboard_em_setup_once(void)
157{
158static char done = 0;
159
160        /* If scanning didn't do anything, passing 0 will setup all interfaces  */
161        if (   !done
162                && rtems_em_pci_setup( mvme5500_em_find_onboard_unit() > 0 ) ) {
163                done=1;
164        }
165}
166
167static void
168onboard_gfe_setup_once(void)
169{
170static char done = 0;
171
172        /* must setup HW address -- note that the label on the
173         * board indicates that the gfe is the second interface
174         * but motLoad etc. interprets the order actually
175         * the other way round...
176         */
177        if (   !done
178                && rtems_gfe_setup( 1, BSP_enetAddr0, BSP_MV64x60_BASE ) > 0 ) {
179                done=1;
180        }
181}
182
183
184/* Find the unit number of the on-board 82544 (even if there is another one
185 * plugged into PMC...
186 *
187 * RETURNS: unit #  (>0) or zero if nothing at all was found. (New board rev.
188 *          with the 82544 hooked to a different IRQ line, new PCI device ID,
189 *          ...)
190 */
191static int
192mvme5500_em_find_onboard_unit(void)
193{
194int unit = 0;
195void *h;
196        /* Determine the on-board 'em' adapter; we know it's interrupt line :-) */
197        for ( h=0; (h=BSP_pciScan(h, scan4irqLine, &unit)); )
198                /* nothing else to do */;
199        return h ? unit : 0;
200}
201
202static int
203mvme5500_em_attach(struct rtems_bsdnet_ifconfig *ifcfg, int attaching)
204{
205        if ( attaching ) {
206                onboard_em_setup_once();
207
208                /* Make sure there is no conflict in MAC address -- see below
209                 * why we 'swap' the addresses. (We actually don't but swap the
210                 * order of the interfaces so they match the label.)
211                 */
212                if ( !ifcfg->hardware_address )
213                        ifcfg->hardware_address = BSP_enetAddr1;
214        }
215
216        return rtems_em_attach(ifcfg, attaching);
217}
218
219static int
220bsp_gfe_attach(struct rtems_bsdnet_ifconfig *ifcfg, int attaching)
221{
222        if ( attaching ) {
223                onboard_gfe_setup_once();
224        }
225        return rtems_gfe_attach(ifcfg, attaching);
226}
227
228BSP_NetIFDesc
229BSP_availableNetIFs(void)
230{
231        if ( IS_6100() )
232                return mvme6100_netifs;
233        if ( IS_5500() )
234                return mvme5500_netifs;
235
236        fprintf(stderr,"BSP_availableNetIFs() -- productIdent not set? unable to identify board type\n");
237
238        return 0;
239}
240
241typedef int (*read_op_t)(int,unsigned);
242typedef int (*write_op_t)(int,unsigned,unsigned);
243
244struct poll_job {
245        read_op_t       rdop;
246        write_op_t      wrop;
247        int                     unit;
248};
249
250static int
251check_phys(struct poll_job *job)
252{
253struct poll_job *j;
254int             rval = -2;
255        for ( j=job; j->rdop; j++ ) {
256                unsigned w;
257                w = j->rdop(j->unit, 1/*status*/);
258                if ( 0x04 & w )    /* active link */
259                        return j-job;
260                if ( !(0x20 & w) ) /* aneg not done   */
261                        rval = -1;     
262        }
263        return rval;
264}
265
266/* check a number of phys
267 * RETURNS: -1 if at least one is still busy
268 *          -2 if all are terminated but no link is found
269 *         >=0 index of first IF with a live link
270 */
271static int
272poll_phys(struct poll_job *job)
273{
274int                             rval;
275struct poll_job *j   = job;
276int             retry = 4;
277
278        /* see if we already have a link */
279        if ( (rval=check_phys(job)) < 0 ) {
280                /* no - start negotiation */
281                for ( j = job; j->rdop; j++ ) {
282                        j->wrop(j->unit, 0/* ctrl */, 0x1200 /* start aneg */);
283                }
284
285                do {
286                        sleep(1);
287                } while ( -1 == (rval = check_phys(job)) && retry-- ); 
288        }
289
290        return rval;
291}
292
293
294/* note that detaching is not supported by the current version of the BSD stack */
295int
296BSP_auto_enet_attach(struct rtems_bsdnet_ifconfig *ifcfg, int attaching)
297{
298int             i = -1;
299BSP_NetIFDesc   d = BSP_availableNetIFs();
300struct poll_job job[3];
301
302        if ( !d )
303                return -1;
304
305        /* If they pass a name, find the attach fn */
306        if ( ifcfg->name  && RTEMS_BSP_NETWORK_DRIVER_NAME != ifcfg->name && attaching ) {
307                for (i = 0; d[i].name; i++ ) {
308                        if ( !strcmp(d[i].name, ifcfg->name) ) {
309                                ifcfg->attach = d[i].attach_fn;
310                                break;
311                        }
312                }
313                if ( !d[i].name ) {
314                        fprintf(stderr,"WARNING: have no '%s' interface - using default\n", ifcfg->name);
315                        ifcfg->name = 0;
316                }
317        }
318
319        if ( !ifcfg->name || ifcfg->name == RTEMS_BSP_NETWORK_DRIVER_NAME ) {
320                /* automatically choose and attach an interface */
321                if ( RTEMS_BSP_NETWORK_DRIVER_NAME[0] ) {
322                        fprintf(stderr,
323                                        "Configuration error: 'auto' network if already chosen (%s)\n",
324                                        RTEMS_BSP_NETWORK_DRIVER_NAME);
325                        return -1;
326                }
327                if ( IS_6100() ) {
328#define ops rtems_mve_early_link_check_ops
329                        assert(ops.num_slots >= 2);
330                        ops.init(0);
331                        ops.init(1);
332                        job[0].rdop = ops.read_phy;
333                        job[0].wrop = ops.write_phy;
334                        job[0].unit = 0;
335                        job[1].rdop = ops.read_phy;
336                        job[1].wrop = ops.write_phy;
337                        job[1].unit = 1;
338#undef ops
339                } else if ( IS_5500() ) {
340#define opsgfe rtems_gfe_early_link_check_ops
341#define opsem  rtems_em_early_link_check_ops
342                        assert(opsgfe.num_slots >= 1);
343                        onboard_gfe_setup_once();
344                        opsgfe.init(0);
345                        assert(opsem.num_slots >= 1);
346                        onboard_em_setup_once();
347                        opsem.init(0);
348                        job[0].rdop = opsem.read_phy;
349                        job[0].wrop = opsem.write_phy;
350                        job[0].unit = 0;
351                        job[1].rdop = opsgfe.read_phy;
352                        job[1].wrop = opsgfe.write_phy;
353                        job[1].unit = 0;
354#undef opsgfe
355#undef opsem
356                }
357                job[2].rdop = 0; /* tag end */
358                i = poll_phys(job);
359                if ( i >= 0 ) {
360                        printf("L");
361                } else {
362                        i = 0;
363                        printf("No l");
364                }
365                printf("ink detected; attaching %s\n",d[i].name);
366
367                /* set attach function and IF name */
368                ifcfg->attach = d[i].attach_fn;
369                ifcfg->name   = RTEMS_BSP_NETWORK_DRIVER_NAME;
370                strcpy(RTEMS_BSP_NETWORK_DRIVER_NAME, d[i].name);
371        }
372        return ifcfg->attach(ifcfg, attaching);
373}
374
375/* from 'em' */
376
377/* PCI Device IDs */
378#define E1000_DEV_ID_82542               0x1000
379#define E1000_DEV_ID_82543GC_FIBER       0x1001
380#define E1000_DEV_ID_82543GC_COPPER      0x1004
381#define E1000_DEV_ID_82544EI_COPPER      0x1008
382#define E1000_DEV_ID_82544EI_FIBER       0x1009
383#define E1000_DEV_ID_82544GC_COPPER      0x100C
384#define E1000_DEV_ID_82544GC_LOM         0x100D
385#define E1000_DEV_ID_82540EM             0x100E
386#define E1000_DEV_ID_82541ER_LOM         0x1014
387#define E1000_DEV_ID_82540EM_LOM         0x1015
388#define E1000_DEV_ID_82540EP_LOM         0x1016
389#define E1000_DEV_ID_82540EP             0x1017
390#define E1000_DEV_ID_82540EP_LP          0x101E
391#define E1000_DEV_ID_82545EM_COPPER      0x100F
392#define E1000_DEV_ID_82545EM_FIBER       0x1011
393#define E1000_DEV_ID_82545GM_COPPER      0x1026
394#define E1000_DEV_ID_82545GM_FIBER       0x1027
395#define E1000_DEV_ID_82545GM_SERDES      0x1028
396#define E1000_DEV_ID_82546EB_COPPER      0x1010
397#define E1000_DEV_ID_82546EB_FIBER       0x1012
398#define E1000_DEV_ID_82546EB_QUAD_COPPER 0x101D
399#define E1000_DEV_ID_82541EI             0x1013
400#define E1000_DEV_ID_82541EI_MOBILE      0x1018
401#define E1000_DEV_ID_82541ER             0x1078
402#define E1000_DEV_ID_82547GI             0x1075
403#define E1000_DEV_ID_82541GI             0x1076
404#define E1000_DEV_ID_82541GI_MOBILE      0x1077
405#define E1000_DEV_ID_82541GI_LF          0x107C
406#define E1000_DEV_ID_82546GB_COPPER      0x1079
407#define E1000_DEV_ID_82546GB_FIBER       0x107A
408#define E1000_DEV_ID_82546GB_SERDES      0x107B
409#define E1000_DEV_ID_82546GB_PCIE        0x108A
410#define E1000_DEV_ID_82547EI             0x1019
411#define E1000_DEV_ID_82547EI_MOBILE      0x101A
412#define E1000_DEV_ID_82573E              0x108B
413#define E1000_DEV_ID_82573E_IAMT         0x108C
414
415#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099
416
417static unsigned em_info[] =
418{
419        /* Intel(R) PRO/1000 Network Connection */
420        E1000_DEV_ID_82540EM,
421        E1000_DEV_ID_82540EM_LOM,
422        E1000_DEV_ID_82540EP,
423        E1000_DEV_ID_82540EP_LOM,
424        E1000_DEV_ID_82540EP_LP,
425
426        E1000_DEV_ID_82541EI,
427        E1000_DEV_ID_82541ER,
428        E1000_DEV_ID_82541ER_LOM,
429        E1000_DEV_ID_82541EI_MOBILE,
430        E1000_DEV_ID_82541GI,
431        E1000_DEV_ID_82541GI_LF,
432        E1000_DEV_ID_82541GI_MOBILE,
433
434        E1000_DEV_ID_82542,
435
436        E1000_DEV_ID_82543GC_FIBER,
437        E1000_DEV_ID_82543GC_COPPER,
438
439        E1000_DEV_ID_82544EI_COPPER,
440        E1000_DEV_ID_82544EI_FIBER,
441        E1000_DEV_ID_82544GC_COPPER,
442        E1000_DEV_ID_82544GC_LOM,
443
444        E1000_DEV_ID_82545EM_COPPER,
445        E1000_DEV_ID_82545EM_FIBER,
446        E1000_DEV_ID_82545GM_COPPER,
447        E1000_DEV_ID_82545GM_FIBER,
448        E1000_DEV_ID_82545GM_SERDES,
449
450        E1000_DEV_ID_82546EB_COPPER,
451        E1000_DEV_ID_82546EB_FIBER,
452        E1000_DEV_ID_82546EB_QUAD_COPPER,
453        E1000_DEV_ID_82546GB_COPPER,
454        E1000_DEV_ID_82546GB_FIBER,
455        E1000_DEV_ID_82546GB_SERDES,
456        E1000_DEV_ID_82546GB_PCIE,
457        E1000_DEV_ID_82546GB_QUAD_COPPER,
458
459        E1000_DEV_ID_82547EI,
460        E1000_DEV_ID_82547EI_MOBILE,
461        E1000_DEV_ID_82547GI,
462
463        E1000_DEV_ID_82573E,
464        E1000_DEV_ID_82573E_IAMT,
465
466        /* required last entry */
467        0,
468};
Note: See TracBrowser for help on using the repository browser.