OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [arm/] [xscale/] [iq80321/] [v2_0/] [src/] [diag/] [i82544.c] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//=============================================================================
2
//
3
//      i82544.c.c - Diagnostic support for i82544 NIC
4
//
5
//=============================================================================
6
//####ECOSGPLCOPYRIGHTBEGIN####
7
// -------------------------------------------
8
// This file is part of eCos, the Embedded Configurable Operating System.
9
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
10
//
11
// eCos is free software; you can redistribute it and/or modify it under
12
// the terms of the GNU General Public License as published by the Free
13
// Software Foundation; either version 2 or (at your option) any later version.
14
//
15
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
16
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
17
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18
// for more details.
19
//
20
// You should have received a copy of the GNU General Public License along
21
// with eCos; if not, write to the Free Software Foundation, Inc.,
22
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23
//
24
// As a special exception, if other files instantiate templates or use macros
25
// or inline functions from this file, or you compile this file and link it
26
// with other works to produce a work based on this file, this file does not
27
// by itself cause the resulting work to be covered by the GNU General Public
28
// License. However the source code for this file must still be made available
29
// in accordance with section (3) of the GNU General Public License.
30
//
31
// This exception does not invalidate any other reasons why a work based on
32
// this file might be covered by the GNU General Public License.
33
//
34
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
35
// at http://sources.redhat.com/ecos/ecos-license/
36
// -------------------------------------------
37
//####ECOSGPLCOPYRIGHTEND####
38
//=============================================================================
39
//#####DESCRIPTIONBEGIN####
40
//
41
// Author(s):    Mark Salter
42
// Contributors: 
43
// Date:         2002-01-25
44
// Purpose:     
45
// Description: 
46
//
47
//####DESCRIPTIONEND####
48
//
49
//===========================================================================*/
50
 
51
#include <redboot.h>
52
#include <cyg/io/pci.h>
53
#include "test_menu.h"
54
 
55
extern int diag_ishex(char theChar);
56
extern int diag_hex2dec(char hex);
57
 
58
#define READMEM8(   _reg_, _val_ ) ((CYG_BYTE)(_val_) = *((volatile CYG_BYTE *)(_reg_)))
59
#define WRITEMEM8(  _reg_, _val_ ) (*((volatile CYG_BYTE *)(_reg_)) = (CYG_BYTE)(_val_))
60
#define READMEM16(  _reg_, _val_ ) ((CYG_WORD16)(_val_) = *((volatile CYG_WORD16 *)(_reg_)))
61
#define WRITEMEM16( _reg_, _val_ ) (*((volatile CYG_WORD16 *)(_reg_)) = (CYG_WORD16)(_val_))
62
#define READMEM32(  _reg_, _val_ ) ((CYG_WORD32)(_val_) = *((volatile CYG_WORD32 *)(_reg_)))
63
#define WRITEMEM32( _reg_, _val_ ) (*((volatile CYG_WORD32 *)(_reg_)) = (CYG_WORD32)(_val_))
64
#define READMEM64(  _reg_, _val_ ) ((CYG_WORD64)(_val_) = *((volatile CYG_WORD64 *)(_reg_)))
65
#define WRITEMEM64( _reg_, _val_ ) (*((volatile CYG_WORD64 *)(_reg_)) = (CYG_WORD64)(_val_))
66
 
67
#define OUTL( _v_, _a_ ) WRITEMEM32( _a_, _v_ )
68
 
69
static inline cyg_uint32 INL(cyg_uint32 io_address)
70
 {   cyg_uint32 _t_; READMEM32( io_address, _t_ ); return _t_;   }
71
 
72
// ------------------------------------------------------------------------
73
//
74
// Serial EEPROM access  - much like the other Intel ethernet
75
//
76
 
77
#define EE_SHIFT_CLK    0x01            // EEPROM shift clock.
78
#define EE_CS           0x02            // EEPROM chip select.
79
#define EE_DATA_WRITE   0x04            // EEPROM chip data in.
80
#define EE_DATA_READ    0x08            // EEPROM chip data out.
81
#define EE_ENB          (0x10|EE_CS)
82
 
83
#define EE_DELAY() do { int z; for ( z = 0; z < 10000; z++ ) ; } while (0)
84
 
85
#if 0
86
# define EE_PRINTF diag_printf
87
# define EE_STUFF "%4s | %4s | %4s | %4s [%08x]\n",     \
88
    (l & EE_SHIFT_CLK) ? "CLK"  : "clk",                      \
89
    (l & EE_CS) ? "eeCS" : "--",                       \
90
    (l & EE_DATA_WRITE) ? "eeDW" : "---",                      \
91
    (l & EE_DATA_READ) ? "eeDR" : "---",                      \
92
    l & 0xfffff
93
#else
94
# define EE_PRINTF( foo )
95
# define EE_STUFF
96
#endif
97
 
98
#define I82544_EECD     0x00010
99
 
100
static inline void
101
ee_select( int ioaddr )
102
{
103
    cyg_uint32 l;
104
    l = EE_ENB;
105
    OUTL( l, ioaddr + I82544_EECD );
106
    EE_DELAY();
107
    l |= EE_CS;
108
    OUTL( l, ioaddr + I82544_EECD );
109
    l = INL( ioaddr + I82544_EECD );
110
    EE_PRINTF( "ee_select       : " EE_STUFF  );
111
    EE_DELAY();
112
}
113
 
114
static inline void
115
ee_deselect( int ioaddr )
116
{
117
    cyg_uint32 l;
118
    l = EE_ENB;
119
    OUTL( l, ioaddr + I82544_EECD );
120
    EE_PRINTF( "ee_deselect 1   : " EE_STUFF  );
121
    EE_DELAY();
122
    EE_DELAY();
123
    EE_DELAY();
124
    l = EE_ENB & ~EE_CS;
125
    OUTL( l, ioaddr + I82544_EECD );
126
    l = INL( ioaddr + I82544_EECD );
127
    EE_PRINTF( "ee_deselect 2   : " EE_STUFF  );
128
    EE_DELAY();
129
    EE_DELAY();
130
    EE_DELAY();
131
}
132
 
133
static inline void
134
ee_clock_up( int ioaddr )
135
{
136
    cyg_uint32 l;
137
    l = INL( ioaddr + I82544_EECD );
138
    l |= EE_SHIFT_CLK;
139
    OUTL( l, ioaddr + I82544_EECD );
140
    EE_DELAY();
141
    l = INL( ioaddr + I82544_EECD );
142
    EE_PRINTF( "ee_clock_up     : " EE_STUFF  );
143
    EE_DELAY();
144
}
145
 
146
static inline void
147
ee_clock_down( int ioaddr )
148
{
149
    cyg_uint32 l;
150
    l = INL( ioaddr + I82544_EECD );
151
    l &=~ EE_SHIFT_CLK;
152
    OUTL( l, ioaddr + I82544_EECD );
153
    EE_DELAY();
154
    l = INL( ioaddr + I82544_EECD );
155
    EE_PRINTF( "ee_clock_down   : " EE_STUFF  );
156
    EE_DELAY();
157
}
158
 
159
static inline int
160
ee_read_data_bit( int ioaddr )
161
{
162
    cyg_uint32 l;
163
    l = INL( ioaddr + I82544_EECD );
164
    EE_PRINTF( "ee_read_data    : " EE_STUFF  );
165
    return EE_DATA_READ == (EE_DATA_READ & l);
166
}
167
 
168
static inline void
169
ee_write_data_bit( int ioaddr, int databit )
170
{
171
    cyg_uint32 l;
172
    l = INL( ioaddr + I82544_EECD );
173
    if ( databit )
174
        l |= EE_DATA_WRITE;
175
    else
176
        l &= ~EE_DATA_WRITE;
177
    OUTL( l, ioaddr + I82544_EECD );
178
    l = INL( ioaddr + I82544_EECD );
179
    EE_PRINTF( "ee_write_data   : " EE_STUFF  );
180
    EE_DELAY();
181
}
182
 
183
// Pass ioaddr around "invisibly"
184
#define EE_SELECT()              ee_select(ioaddr)
185
#define EE_DESELECT()            ee_deselect(ioaddr)
186
#define EE_CLOCK_UP()            ee_clock_up(ioaddr)
187
#define EE_CLOCK_DOWN()          ee_clock_down(ioaddr)
188
#define EE_READ_DATA_BIT()       ee_read_data_bit(ioaddr)
189
#define EE_WRITE_DATA_BIT( _d_ ) ee_write_data_bit(ioaddr,(_d_))
190
 
191
// ------------------------------------------------------------------------
192
 
193
static int
194
read_eeprom_word( cyg_uint32 ioaddr, int addrbits, int address )
195
{
196
    int i, tmp;
197
 
198
    // Should already be not-selected, but anyway:
199
    EE_SELECT();
200
 
201
    // Shift the read command bits out.
202
    for (i = 3; i >= 0; i--) { // Doc says to shift out a zero then:
203
        tmp = (6 & (1 << i)) ? 1 : 0; // "6" is the "read" command.
204
        EE_WRITE_DATA_BIT(tmp);
205
        EE_CLOCK_UP();
206
        EE_CLOCK_DOWN();
207
    }
208
 
209
    // Now clock out address
210
    for ( i = addrbits - 1; i >= 0 ; i-- ) {
211
        tmp = (address & (1<<i)) ? 1 : 0;
212
        EE_WRITE_DATA_BIT(tmp);
213
        EE_CLOCK_UP();
214
        tmp = EE_READ_DATA_BIT();
215
        EE_CLOCK_DOWN();
216
 
217
//        CYG_ASSERT( (0 == tmp) == (0 == i), "Looking for zero handshake bit" );
218
    }
219
 
220
    // read in the data
221
    tmp = 0;
222
    for (i = 15; i >= 0; i--) {
223
        EE_CLOCK_UP();
224
        if ( EE_READ_DATA_BIT() )
225
            tmp |= (1<<i);
226
        EE_CLOCK_DOWN();
227
    }
228
 
229
    // Terminate the EEPROM access.
230
    EE_DESELECT();
231
 
232
#ifdef DEBUG_EE
233
//    diag_printf( "eeprom address %4x: data %4x\n", address, tmp );
234
#endif
235
 
236
    return tmp;
237
}
238
 
239
// ------------------------------------------------------------------------
240
static void
241
write_eeprom_word( cyg_uint32 ioaddr, int addrbits, int address, cyg_uint16 value)
242
{
243
    int i, tmp;
244
 
245
    // Should already be not-selected, but anyway:
246
    EE_SELECT();
247
 
248
    // Shift the write command bits out.
249
    for (i = 3; i >= 0; i--) {          // Doc says to shift out a zero then:
250
        tmp = (5 & (1 << i)) ? 1 : 0;   // "5" is the "write" command.
251
        EE_WRITE_DATA_BIT(tmp);
252
        EE_CLOCK_UP();
253
        EE_CLOCK_DOWN();
254
    }
255
 
256
    // Now clock out address
257
    for ( i = addrbits - 1; i >= 0 ; i-- ) {
258
        tmp = (address & (1<<i)) ? 1 : 0;
259
        EE_WRITE_DATA_BIT(tmp);
260
        EE_CLOCK_UP();
261
        tmp = EE_READ_DATA_BIT();
262
        EE_CLOCK_DOWN();
263
    }
264
 
265
 
266
    // write the data
267
    for (i = 15; i >= 0; i--) {
268
        tmp = (value & (1 << i)) ? 1 : 0;
269
        EE_WRITE_DATA_BIT(tmp);
270
        EE_CLOCK_UP();
271
        EE_CLOCK_DOWN();
272
    }
273
 
274
    // Terminate the EEPROM access.
275
    EE_DESELECT();
276
 
277
    CYGACC_CALL_IF_DELAY_US((cyg_int32)15*1000);
278
}
279
 
280
// ------------------------------------------------------------------------
281
static int
282
write_enable_eeprom(cyg_uint32 ioaddr, int addrbits)
283
{
284
    int i, tmp;
285
 
286
    // Should already be not-selected, but anyway:
287
    EE_SELECT();
288
 
289
    // Shift the EWEN command bits out.
290
    for (i = 5; i >= 0; i--) {           // Doc says to shift out a zero then:
291
        tmp = (0x13 & (1 << i)) ? 1 : 0; // "0x13" is the "EWEN" command.
292
        EE_WRITE_DATA_BIT(tmp);
293
        EE_CLOCK_UP();
294
        EE_CLOCK_DOWN();
295
    }
296
 
297
    // Shift the rest of the address bits out. (ignored)
298
    // Two bits were used for the EWEN command above.
299
    tmp = 0;
300
    for (i = (addrbits-3); i >= 0; i--) {
301
        EE_WRITE_DATA_BIT(tmp);
302
        EE_CLOCK_UP();
303
        EE_CLOCK_DOWN();
304
    }
305
 
306
    // Terminate the EEPROM access.
307
    EE_DESELECT();
308
}
309
 
310
 
311
// ------------------------------------------------------------------------
312
static void
313
program_eeprom(cyg_uint32 ioaddr, int addrbits, cyg_uint16 *data)
314
{
315
    cyg_uint32 i;
316
    cyg_uint16 checksum = 0;
317
 
318
    // First enable erase/write operations on the eeprom.
319
    // This is done through the EWEN instruction.
320
    write_enable_eeprom(ioaddr, addrbits);
321
 
322
    for (i = 0; i < 63; i++, data++) {
323
        checksum += *data;
324
        write_eeprom_word(ioaddr, addrbits, i, *data);
325
    }
326
    checksum = 0xBABA - checksum;
327
    write_eeprom_word(ioaddr, addrbits, i, checksum);
328
}
329
 
330
// Get MAC address from user.
331
// Acceptable formats are:
332
//   nn.nn.nn.nn.nn.nn
333
//   nn:nn:nn:nn:nn:nn
334
//   nn-nn-nn-nn-nn-nn
335
//   nn nn nn nn nn nn
336
//   nnnnnnnnnnnn
337
static void
338
get_mac_address(char *addr_buf)
339
{
340
    char input[40], mac[6], *p;
341
    int got, i;
342
 
343
    do {
344
        got = 0;
345
        diag_printf ("\nCurrent MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n",
346
                     addr_buf[0], addr_buf[1], addr_buf[2],
347
                     addr_buf[3], addr_buf[4], addr_buf[5]);
348
        diag_printf ("Enter desired MAC address: ");
349
        while (_rb_gets(input, sizeof(input), 0) != _GETS_OK)
350
            ;
351
 
352
        p = input;
353
        while (*p && *p == ' ');
354
 
355
        if (p[0] == '\0' || p[1] == '\0')
356
            continue;
357
 
358
        for (; got < 6; got++) {
359
            if (!diag_ishex(p[0]) || !diag_ishex(p[1]))
360
                break;
361
            mac[got] = (diag_hex2dec(p[0]) * 16) + diag_hex2dec(p[1]);
362
            p += 2;
363
            if (*p == '.' || *p == ':' || *p == ' ' || *p == '-')
364
                p++;
365
        }
366
    } while (got != 6);
367
 
368
    for (i = 0; i < 6; i++)
369
        *addr_buf++ = mac[i];
370
}
371
 
372
 
373
static cyg_uint16 eeprom_defaults[] = {
374
/* halfword addresses! */
375
/*  0: */  0x0000,  0x0000,  0x0000,  0x0000,
376
/*  4: */  0x0000,  0x0000,  0x0000,  0x0000,
377
/*  8: */  0x0000,  0x0000,  0x4e0b,  0x1008,
378
/*  C: */  0x8086,  0x1008,  0x8086,  0xf02c,
379
/* 10: */  0xffff,  0xffff,  0xffff,  0xffff,
380
/* 14: */  0xffff,  0xffff,  0xffff,  0xffff,
381
/* 18: */  0xffff,  0xffff,  0xffff,  0xffff,
382
/* 1C: */  0xffff,  0xffff,  0xffff,  0xffff,
383
/* 20: */  0xdfde,  0x0002,  0x1414,  0xffff,
384
/* 24: */  0xffff,  0xffff,  0xffff,  0xffff,
385
/* 28: */  0xffff,  0xffff,  0xffff,  0xffff,
386
/* 2C: */  0xffff,  0xffff,  0xffff,  0xffff,
387
/* 30: */  0xffff,  0xffff,  0xffff,  0xffff,
388
/* 34: */  0xffff,  0xffff,  0xffff,  0xffff,
389
/* 38: */  0xffff,  0xffff,  0xffff,  0xffff,
390
/* 3C: */  0xffff,  0xffff,  0xffff,  0x0000,
391
};
392
 
393
/* Setup Serial EEPROM for Ethernet Configuration */
394
void
395
enet_setup (MENU_ARG arg)
396
{
397
    cyg_pci_device dev_info;
398
    cyg_pci_device_id devid;
399
    cyg_uint16 cksum;
400
    cyg_uint16 eeprom_data[64];
401
    cyg_uint32 nic_addr;
402
    int i, bus;
403
 
404
    // First, look for NIC at private and public addresses
405
 
406
    bus = (*ATU_PCIXSR >> 8) & 0xff;
407
    if (bus == 0xff)
408
        bus = 0;
409
 
410
    devid = CYG_PCI_DEV_MAKE_ID(bus, CYG_PCI_DEV_MAKE_DEVFN(__NIC_PUB, 0));
411
    cyg_pci_get_device_info(devid, &dev_info);
412
 
413
    if (dev_info.vendor != 0x8086) {
414
        devid = CYG_PCI_DEV_MAKE_ID(bus, CYG_PCI_DEV_MAKE_DEVFN(__NIC_PRIV, 0));
415
        cyg_pci_get_device_info(devid, &dev_info);
416
        if (dev_info.vendor != 0x8086) {
417
            diag_printf("No i82544 device found\n");
418
            return;
419
        }
420
    }
421
 
422
    nic_addr = dev_info.base_map[0];
423
 
424
    // Now read complete EEPROM contents
425
    for (i = cksum = 0; i < 64; i++) {
426
        eeprom_data[i] = read_eeprom_word(nic_addr, 6, i);
427
        cksum += eeprom_data[i];
428
    }
429
 
430
    // If not valid, initialize to defaults
431
    if (cksum != 0xBABA || (eeprom_data[0x0a] & 0xC000) != 0x4000) {
432
        diag_printf ("Current EEPROM contents invalid. Restoring defaults.\n");
433
        for (i = 0; i < 63; i++)
434
            eeprom_data[i] = eeprom_defaults[i];
435
    }
436
 
437
    get_mac_address((char *)eeprom_data);
438
 
439
    // Now compute checksum on complete EEPROM contents
440
    for (i = cksum = 0; i < 63; i++)
441
        cksum += eeprom_data[i];
442
 
443
    eeprom_data[63] = 0xBABA - cksum;
444
 
445
    diag_printf ("Writing to the Serial EEPROM... ");
446
    program_eeprom(nic_addr, 6, eeprom_data);
447
    diag_printf ("Done\n");
448
 
449
    /* now that we have finished writing the configuration data, we must ask the
450
       operator to reset the board to have the configuration changes take effect.
451
       After the reset, the standard Enet. port diagnostics can be run on the
452
       board under test */
453
 
454
    diag_printf ("\n******** Reset The Board To Have Changes Take Effect ********\n");
455
}
456
 
457
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.