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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [arm/] [xscale/] [iq80310/] [v2_0/] [src/] [diag/] [ether_test.c] - Blame information for rev 565

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//=============================================================================
2
//
3
//      ether_test.c - Cyclone Diagnostics
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):   Scott Coulter, Jeff Frazier, Eric Breeden
42
// Contributors:
43
// Date:        2001-01-25
44
// Purpose:     
45
// Description: 
46
//
47
//####DESCRIPTIONEND####
48
//
49
//===========================================================================*/
50
#include <redboot.h>
51
#include <cyg/io/pci_hw.h>
52
#include <cyg/io/pci.h>
53
#include "pci_bios.h"
54
#include "iq80310.h"
55
#include "ether_test.h"
56
 
57
/* Forward declarations */
58
static int i557SelfTest (void);
59
static int i557Init (void);
60
static int i557Config (UINT8 loopBackMode);
61
static int i557AddrSet (void);
62
static int i557RUStart (void);
63
static void setUpPacket (char *p);
64
static int txPacket (char *p);
65
static char *malloc (int n);
66
static int waitForRxInt(void);
67
static int get_ether_addr(int unit, UINT8 *buf, int print_flag);
68
 
69
/* Externals */
70
extern long decIn(void);
71
extern void sgets(char *s);
72
extern int enable_external_interrupt (int int_id);
73
extern int isr_connect(int int_num, void (*handler)(int), int arg);
74
extern STATUS pci_isr_connect (int intline, int bus, int device, int (*handler)(int), int arg);
75
extern void delay_ms(int msecs);
76
 
77
extern int eeprom_read (UINT32 pci_base,/* PCI Base address */
78
                 int eeprom_addr,       /* word offset from start of eeprom */
79
                 UINT16 *p_data,/* where to put data in memory */
80
                 int nwords             /* number of 16bit words to read */
81
                 );
82
extern int eeprom_write (UINT32 pci_base,/* PCI Base address */
83
                 int eeprom_addr,       /* word offset from start of eeprom */
84
                 UINT16 *p_data,/* data location in memory */
85
                 int nwords             /* number of 16bit words to write */
86
                 );
87
 
88
/* Globals needed by both main program and irq handler */
89
static volatile struct SCBtype *pSCB;   /* Pointer to SCB in use */
90
static volatile UINT32 waitSem; /* Used to block test until interrupt */
91
static volatile UINT32 rxSem;   /* Used to block test until rx sinterrupt */
92
static UINT16 i557Status;       /* Status code from SCB */
93
static volatile char *mem_pool; /* Ptr to malloc's free memory pool */
94
static UINT32 adapter[2];               /* Ptr to PCI Ethernet adapter */
95
static UINT8 node_address[6];
96
/*static long timer0_ticks = 0;*/
97
static char buf[4];
98
static int count = 0;
99
static int forever_flag = FALSE;
100
static UINT32 phy_id = 0;
101
 
102
/* 82557 required data structures which must be allocated */
103
static struct rfd *pRfd;
104
static union cmdBlock *pCmdBlock;
105
static char *pPacketBuf;
106
 
107
#define SPEED_NOLINK    0
108
#define SPEED_10M       10
109
#define SPEED_100M      100
110
static int link_speed = SPEED_NOLINK;
111
 
112
UINT8 unit_intpin;
113
int unit_devno, unit_busno, unit_funcno;
114
 
115
#define BUSY_WAIT_LIMIT  0xf000  /* the upper limit on a busy wait
116
                                    for command completion, etc. */
117
 
118
static void mask_557_ints (void)
119
{
120
    pSCB->cmdStat.bits.m = 1;
121
}
122
 
123
static void unmask_557_ints (void)
124
{
125
    pSCB->cmdStat.bits.m = 0;
126
}
127
 
128
/*****************************************************************************
129
* pci_ether_test - i8255x PCI Ethernet test
130
*
131
* Main diagnostic routine for the Intel 8255x 10/100BaseT Ethernet Controller
132
* family.  Arguments include the PCI bus, device and function numbers of the
133
* controller that is to be tested.
134
*
135
*/
136
void pci_ether_test (UINT32 busno, UINT32 devno, UINT32 funcno)
137
{
138
    volatile int i;
139
    int ntimes;
140
    int broadcom_flag =  FALSE;
141
    UINT16 phy_addr_reg, temp1, temp2;
142
    cyg_pci_device_id  devid;
143
 
144
    count = 0;
145
 
146
    devid = CYG_PCI_DEV_MAKE_ID(busno, CYG_PCI_DEV_MAKE_DEVFN(devno,funcno));
147
 
148
    /* read the PCI BAR for the Ethernet controller */
149
    cyg_pci_read_config_uint32(devid, 0x10, &adapter[0]);
150
 
151
    /* strip off BAR indicator bits */
152
    adapter[0] &= 0xfffffff0;
153
 
154
    unit_devno  = devno;
155
    unit_busno  = busno;
156
    unit_funcno = funcno;
157
 
158
    /* pointer to on-chip SCB */
159
    pSCB = (struct SCBtype *)(adapter[0] + SCB_OFFSET);
160
 
161
    unit_intpin = INTA;
162
 
163
    printf ("PCI Base Address  = 0x%X\n", adapter[0]);
164
    printf ("PCI Interrupt Pin = 0x%02X\n", unit_intpin);
165
 
166
    /* Initialize malloc's memory pool pointer */
167
    mem_pool = (char *) ETHER_MEM_POOL;
168
 
169
    /* Start the timer for delay implementation
170
       printf("Starting timer... ");
171
       StartTimer(); */
172
    printf("Done.\n Resetting chip... ");
173
 
174
    /* reset the 82557 to start with a clean slate */
175
    resetChip();
176
    printf("Done.\n");
177
 
178
    /* Get the UUT's ethernet address */
179
    if (get_ether_addr (0, node_address, TRUE) == ERROR) {
180
        printf("Error Reading Adapter Ethernet Address\n");
181
        return;
182
    }
183
 
184
    temp1 = readMDI(0, MDI_DEFAULT_PHY_ADDR, MDI_PHY_ID_1);
185
    temp2 = readMDI(0, MDI_DEFAULT_PHY_ADDR, MDI_PHY_ID_2);
186
    phy_id = ((temp1 << 16) | temp2);
187
 
188
    if ((phy_id & 0xfffffff0) == I82555_PHY_ID) {
189
        printf ("Intel 82555/558 PHY detected...\n");
190
 
191
        /* dummy read for reliable status */
192
        (void)readMDI (0, MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT);
193
 
194
        temp1 = readMDI (0, MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT);
195
        printf ("Status Register Link Status is %s\n", (temp1 & MDI_STAT_LINK) ? "UP" : "DOWN");
196
 
197
        phy_addr_reg = readMDI (0, MDI_DEFAULT_PHY_ADDR, I82555_STATCTRL_REG);
198
 
199
        if (temp1 & MDI_STAT_LINK) {    /* speed only valid with good LNK */
200
            printf ("Connect Speed is %s\n", (phy_addr_reg & I82555_100_MBPS) ? "100Mbps" : "10Mbps");
201
            link_speed = (phy_addr_reg & I82555_100_MBPS) ? SPEED_100M : SPEED_10M;
202
        } else
203
            printf ("Connect Speed is NOT VALID\n");
204
    }
205
 
206
    if ((phy_id & 0xfffffff0) == ICS1890_PHY_ID) {
207
        printf ("Integrated Circuit Systems ICS1890 PHY detected...\n");
208
        printf ("Revision = %c\n", 'A' + (phy_id & REVISION_MASK));
209
 
210
        /* dummy read for reliable status */
211
        (void)readMDI (0, MDI_DEFAULT_PHY_ADDR, ICS1890_QUICKPOLL_REG);
212
        temp1 = readMDI (0, MDI_DEFAULT_PHY_ADDR, ICS1890_QUICKPOLL_REG);
213
        printf ("Status Register Link Status is %s\n", (temp1 & QUICK_LINK_VALID) ? "UP" : "DOWN");
214
 
215
        if (temp1 & QUICK_LINK_VALID) { /* speed only valid with good LNK */
216
            printf ("Connect Speed is %s\n", (temp1 & QUICK_100_MBPS) ? "100Mbps" : "10Mbps");
217
            link_speed = (temp1 & QUICK_100_MBPS) ?
218
                SPEED_100M : SPEED_10M;
219
        } else
220
            printf ("Connect Speed is NOT VALID\n");
221
    }
222
 
223
    if ((phy_id & 0xfffffff0) == DP83840_PHY_ID) {
224
        printf ("National DP83840 PHY detected...\n");
225
        printf ("Revision = %c\n", 'A' + (phy_id & REVISION_MASK));
226
 
227
        /* dummy read for reliable status */
228
        (void)readMDI (0, MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT);
229
        temp1 = readMDI (0, MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT);
230
        printf ("Status Register Link Status is %s\n", (temp1 & MDI_STAT_LINK) ? "UP" : "DOWN");
231
 
232
        phy_addr_reg = readMDI (0 ,MDI_DEFAULT_PHY_ADDR, DP83840_PHY_ADDR_REG);
233
 
234
        if (temp1 & MDI_STAT_LINK) {    /* speed only valid with good LNK */
235
            printf ("Connect Speed is %s\n", (phy_addr_reg & PHY_ADDR_SPEED_10_MBPS) ? "10Mbps" : "100Mbps");
236
            link_speed = (phy_addr_reg & PHY_ADDR_SPEED_10_MBPS) ? SPEED_10M : SPEED_100M;
237
        }
238
        else printf ("Connect Speed is NOT VALID\n");
239
    }
240
 
241
    if ((phy_id & 0xfffffff0) == I82553_PHY_ID) {
242
        printf ("Intel 82553 PHY detected...\n");
243
        printf ("Revision = %c\n", 'A' + (phy_id & REVISION_MASK));
244
        broadcom_flag = TRUE;
245
    }
246
 
247
    if (phy_id == I82553_REVAB_PHY_ID) {
248
        printf ("Intel 82553 PHY detected...\n");
249
        printf ("Revision = B\n");
250
        broadcom_flag = TRUE;
251
    }
252
 
253
    if (broadcom_flag == TRUE) {
254
        temp2 = readMDI (0,MDI_DEFAULT_PHY_ADDR, I82553_PHY_EXT_REG0);
255
        printf ("Stepping = %02X\n", GET_REV_CNTR(temp2));
256
 
257
        /* dummy read for reliable status */
258
        (void)readMDI (0 ,MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT);
259
        temp1 = readMDI (0 ,MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT);
260
        printf ("Status Register Link Status is %s\n", (temp1 & MDI_STAT_LINK) ? "UP" : "DOWN");
261
 
262
        if (temp1 & MDI_STAT_LINK) {    /* speed only valid with good LNK */
263
            printf ("Connect Speed is %s\n", (temp2 & EXT_REG0_100_MBPS) ? "100Mbps" : "10Mbps");
264
            link_speed = (temp2 & EXT_REG0_100_MBPS) ? SPEED_100M : SPEED_10M;
265
        } else
266
            printf ("Connect Speed is NOT VALID\n");
267
    }
268
    printf ("\n");
269
 
270
    /* Run the built-in self test through the port register */
271
    if (i557SelfTest () == ERROR) {
272
        mask_557_ints ();      /* Disable 557 interrupt */
273
        return;
274
    }
275
 
276
    /* Reset clears the interrupt mask */
277
    mask_557_ints();
278
 
279
    printf ("Press return to initialize ethernet controller.\n");
280
    sgets (buf);
281
 
282
    /* Initialize data structures */
283
    if (i557Init () == ERROR) {
284
        mask_557_ints ();      /* Disable 557 interrupt */
285
        return;
286
    }
287
 
288
    /* Set hardware address */
289
    if (i557AddrSet () == ERROR) {
290
        mask_557_ints ();      /* Disable 557 interrupt */
291
        return;
292
    }
293
 
294
    printf ("Press return to perform internal loopback test.\n");
295
    sgets (buf);
296
 
297
    /* Configure for internal loopback */
298
    if (i557Config (INT_LOOP_BACK) == ERROR) {
299
        mask_557_ints ();      /* Disable 557 interrupt */
300
        return;
301
    }
302
 
303
    delay_ms(100);
304
 
305
    /* Initialize receive buffer and enable receiver */
306
    if (i557RUStart () == ERROR) {
307
        mask_557_ints ();      /* Disable 557 interrupt */
308
        return;
309
    }
310
 
311
    /* Send a packet */
312
    setUpPacket (pPacketBuf);
313
    if (txPacket (pPacketBuf) == ERROR) {
314
        mask_557_ints ();      /* Disable 557 interrupt */
315
        return;
316
    }
317
 
318
    printf ("Press return to perform loopback through PHY.\n");
319
    sgets (buf);
320
 
321
    /* Configure for external loopback */
322
    if (i557Config (EXT_LOOP_BACK) == ERROR) {
323
        mask_557_ints ();      /* Disable 557 interrupt */
324
        return;
325
    }
326
 
327
    delay_ms(100);
328
 
329
    /* Initialize receive buffer and enable receiver */
330
    if (i557RUStart () == ERROR) {
331
        mask_557_ints ();      /* Disable 557 interrupt */
332
        return;
333
    }
334
 
335
    /* Send a packet */
336
    setUpPacket (pPacketBuf);
337
    if (txPacket (pPacketBuf) == ERROR) {
338
        mask_557_ints ();      /* Disable 557 interrupt */
339
        return;
340
    }
341
 
342
    printf ("Press return to perform external loopback through\n");
343
    printf ("10/100 Base T Hub.  NOTE: If test duration is not forever,\n");
344
    printf ("this test will work only if a properly functioning Hub\n");
345
    printf ("and Twisted Pair cable are attached to the network connector\n");
346
    printf ("on the front panel.\n");
347
    sgets (buf);
348
 
349
    printf ("Enter the number of times to run test (0 = forever): ");
350
    ntimes = decIn();
351
    printf ("\n\n");
352
 
353
    if (i557RUStart () == ERROR) {
354
        mask_557_ints ();      /* Disable 557 interrupt */
355
        return;
356
    }
357
 
358
    setUpPacket (pPacketBuf);
359
 
360
    if (ntimes == 0) {
361
        forever_flag = TRUE;
362
 
363
        while (1) {
364
            if ((i557RUStart() == ERROR)||(txPacket (pPacketBuf) == ERROR)) {
365
                printf ("Double-check TP cable and 10/100 Base T Hub\n");
366
                printf ("Try testing them with another system\n");
367
                printf ("(such as a workstation) that is working correctly.\n");
368
                mask_557_ints ();      /* Disable 557 interrupt */
369
                return;
370
            }
371
 
372
            count++;
373
            if (((count) % 1000) == 0)
374
                printf("Loopback Cycle Count = %d\n", count);
375
        }
376
    } else {
377
        forever_flag = FALSE;
378
 
379
        for (i=0; i<ntimes; i++) {
380
            if ((i557RUStart() == ERROR)||(txPacket (pPacketBuf) == ERROR)) {
381
                printf ("Double-check TP cable and 10/100 Base T Hub\n");
382
                printf ("Try testing them with another system\n");
383
                printf ("(such as a workstation) that is working correctly.\n");
384
                mask_557_ints ();      /* Disable 557 interrupt */
385
                return;
386
            }
387
 
388
            count++;
389
            printf("Loopback Cycle Count = %d\n", count);
390
        }
391
 
392
        /* It worked! */
393
 
394
        mask_557_ints ();       /* Disable 557 interrupt */
395
 
396
        printf ("\nEthernet controller passed.  Press return to continue.\n");
397
 
398
        sgets (buf);
399
    }
400
}
401
 
402
 
403
/* Perform internal self test - returns OK if sucessful, ERROR if not. */
404
static int i557SelfTest ()
405
{
406
    volatile struct selfTest *pSelfTestMem;
407
    UINT32 oldWord2;
408
    long delay;
409
    UINT32 temp;
410
    int rtnVal;
411
 
412
    /* reset the 82557 to start with a clean slate */
413
    resetChip();
414
 
415
    /* Allocate some memory for the self test */
416
    pSelfTestMem = (struct selfTest *) malloc (sizeof(struct selfTest));
417
 
418
    if (pSelfTestMem == NULL) {
419
        printf ("Couldn't get memory for self test.\n");
420
        return (ERROR);
421
    }
422
 
423
    printf ("Sending PORT* self-test command...\n");
424
    printf ("Local Dump address = 0x%X\n", pSelfTestMem);
425
 
426
    /* Set all bits in  second word, wait until it changes or a timeout */
427
    pSelfTestMem->u.word2 = ~0;
428
    oldWord2 = pSelfTestMem->u.word2;
429
 
430
    temp = ((UINT32) pSelfTestMem) + PORT_SELF_TEST;
431
 
432
    portWrite (temp);
433
 
434
    /* Wait for test completion or for timeout */
435
    for (delay = 0; (delay < MAX_DELAY) && (pSelfTestMem->u.word2 == oldWord2); delay++)
436
        ;       /* Wait... */
437
 
438
    /* Print results */
439
    printf ("Self test result: %s\n", (pSelfTestMem->u.bits.selfTest) ? "Fail" : "Pass");
440
    printf ("ROM content test: %s\n", (pSelfTestMem->u.bits.romTest) ? "Fail" : "Pass");
441
    printf ("Register test:    %s\n", (pSelfTestMem->u.bits.regTest) ? "Fail" : "Pass");
442
    printf ("Diagnose test:    %s\n", (pSelfTestMem->u.bits.diagnTest) ? "Fail" : "Pass");
443
    printf ("ROM signature:    0x%X\n", pSelfTestMem->romSig);
444
 
445
    rtnVal = pSelfTestMem->u.bits.selfTest ? ERROR : OK;
446
 
447
    return (rtnVal);
448
}
449
 
450
 
451
/* Initialize the 82557. */
452
static int i557Init (void)
453
{
454
    /* Get memory for system data structures */
455
    if ( ((pRfd = (struct rfd *) malloc (sizeof(struct rfd))) == NULL) ||
456
         ((pPacketBuf = malloc(ETHERMTU + sizeof(UINT16) + 6)) == NULL) ||
457
         ((pCmdBlock = (union cmdBlock *) malloc (sizeof(union cmdBlock))) == NULL) ) {
458
        printf ("Memory allocation failed.\n");
459
        return (ERROR);
460
    }
461
 
462
    /* Set EL bits in command block and rfd so we don't fall of the end */
463
    pCmdBlock->nop.el = END_OF_LIST;
464
    pRfd->el = END_OF_LIST;
465
 
466
    /* Reset chip and initialize */
467
    printf ("Initializing... ");
468
 
469
    /* Reset 82557 */
470
    resetChip ();
471
 
472
    /* set up the CU and RU base values to 0x0 */
473
    sendCommand (LOAD_CU_BASE, RU_NOP, 0);
474
    sendCommand (CU_NOP, LOAD_RU_BASE, 0);
475
 
476
    /* Initialize interrupts */
477
 
478
    /* if it is the onboard i82559, it does not use the conventional PCI
479
       interrupt routines because the interrupt is not multiplexed onto
480
       the PCI bus */
481
    if ((unit_busno == 2) && (unit_devno == 0) && (unit_funcno == 0)) {
482
        if (isr_connect (ENET_INT_ID, (VOIDFUNCPTR)i557IntHandler, 0xdeadbeef) != OK) {
483
            printf ("Error connecting Ethernet interrupt!\n");
484
            return (ERROR);
485
        }
486
        if (enable_external_interrupt (ENET_INT_ID) != OK) {
487
            printf ("Error enabling Ethernet interrupt!\n");
488
            return (ERROR);
489
        }
490
    } else {  /* use regular PCI int connect scheme */
491
        if (pci_isr_connect (unit_intpin, unit_busno, unit_devno, i557IntHandler, 0xdeadbeef) != OK) {
492
            printf ("Error connecting Ethernet interrupt!\n");
493
            return (ERROR);
494
        }
495
    }
496
    unmask_557_ints();
497
    printf ("Done\n");
498
    return (OK);
499
}
500
 
501
 
502
static int initPHY (UINT32 device_type, int loop_mode)
503
{
504
    UINT16 temp_reg;
505
    UINT8 revision;
506
 
507
    /* strip off revision and phy. id information */
508
    revision = (UINT8)(device_type & REVISION_MASK);
509
    device_type &= ~REVISION_MASK;
510
 
511
    switch (device_type) {
512
    case ICS1890_PHY_ID:
513
        temp_reg = readMDI (0, MDI_DEFAULT_PHY_ADDR, MDI_PHY_CTRL);  /* get ready for loopback setting */
514
 
515
        switch (loop_mode) {
516
        case EXT_LOOP_BACK:  /* loopback on the MII interface */
517
            temp_reg |= MDI_CTRL_LOOPBACK;      /* MII loopback */
518
            break;
519
 
520
        case INT_LOOP_BACK:
521
        default:
522
            break;
523
        }
524
 
525
        writeMDI(0, MDI_DEFAULT_PHY_ADDR, MDI_PHY_CTRL, temp_reg);
526
        break;
527
 
528
    case DP83840_PHY_ID:  /* set the Intel-specified "must set" bits */
529
        temp_reg = readMDI (0,MDI_DEFAULT_PHY_ADDR, DP83840_PCR_REG);
530
        temp_reg |= (PCR_TXREADY_SEL | PCR_FCONNECT);
531
        writeMDI (0,MDI_DEFAULT_PHY_ADDR, DP83840_PCR_REG, temp_reg);
532
 
533
        /* get ready for loopback setting */
534
        temp_reg = readMDI (0,MDI_DEFAULT_PHY_ADDR, DP83840_LOOPBACK_REG);
535
        temp_reg &= CLEAR_LOOP_BITS;
536
 
537
        switch (loop_mode) {
538
        case EXT_LOOP_BACK:
539
            temp_reg |= TWISTER_LOOPBACK;
540
            break;
541
 
542
        case INT_LOOP_BACK:
543
        default:
544
            break;
545
        }
546
 
547
        writeMDI (0,MDI_DEFAULT_PHY_ADDR, DP83840_LOOPBACK_REG, temp_reg);
548
        break;
549
 
550
    case I82553_PHY_ID:
551
    case I82553_REVAB_PHY_ID:
552
    case I82555_PHY_ID:
553
        break;
554
 
555
    default:
556
        return (ERROR);
557
        break;
558
    }
559
 
560
    return (OK);
561
}
562
 
563
 
564
/* Set hardware address of the 82557. */
565
static int i557AddrSet ()
566
{
567
    printf ("Setting hardware ethernet address to ");
568
    printf ("%02X:%02X:%02X:", node_address[0], node_address[1], node_address[2]);
569
    printf ("%02X:%02X:%02X... ", node_address[3], node_address[4], node_address[5]);
570
 
571
    /* Set up iaSetup command block and execute */
572
    memset((char *) pCmdBlock, 0, sizeof(union cmdBlock));
573
    pCmdBlock->iaSetup.code = IA_SETUP;
574
    pCmdBlock->iaSetup.el = END_OF_LIST;
575
    memcpy(pCmdBlock->iaSetup.enetAddr, node_address, sizeof(node_address));
576
 
577
    sendCommand (CU_START, RU_NOP, ((UINT32)pCmdBlock));
578
 
579
    if ((waitForInt() == ERROR) || (pCmdBlock->iaSetup.ok != 1)) {
580
        printf ("failed.  Status: 0x%04X.\n", pSCB->cmdStat.words.status);
581
        printf ("C bit = %d\n",pCmdBlock->iaSetup.c);
582
        printf ("OK bit = %d\n",pCmdBlock->iaSetup.ok);
583
        return (ERROR);
584
    }
585
 
586
    printf ("done.\n");
587
    return (OK);
588
}
589
 
590
 
591
/* Configure the 82557. */
592
static int i557Config (UINT8 loopBackMode)      /* None, int, or ext 1, 2 (see etherTest.h) */
593
{
594
    printf ("\nConfiguring for ");
595
 
596
    switch (loopBackMode) {
597
    case INT_LOOP_BACK:
598
        printf ("internal loopback... ");
599
        break;
600
    case EXT_LOOP_BACK:
601
        printf ("external loopback, LPBK* active... ");
602
        break;
603
    default:
604
        printf ("Unknown loopback mode, exiting...\n");
605
        return (ERROR);
606
    }
607
 
608
    /* Set up configure command block and execute */
609
    memset ((char *) pCmdBlock, 0, sizeof(union cmdBlock));
610
    pCmdBlock->configure.code = CONFIGURE;
611
    pCmdBlock->configure.el = END_OF_LIST;
612
    pCmdBlock->configure.configData[ 0] = CONFIG_BYTE_00;
613
    pCmdBlock->configure.configData[ 1] = CONFIG_BYTE_01;
614
    pCmdBlock->configure.configData[ 2] = CONFIG_BYTE_02;
615
    pCmdBlock->configure.configData[ 3] = CONFIG_BYTE_03;
616
    pCmdBlock->configure.configData[ 4] = CONFIG_BYTE_04;
617
    pCmdBlock->configure.configData[ 5] = CONFIG_BYTE_05;
618
    pCmdBlock->configure.configData[ 6] = CONFIG_BYTE_06;
619
    pCmdBlock->configure.configData[ 7] = CONFIG_BYTE_07;
620
    pCmdBlock->configure.configData[ 8] = CONFIG_BYTE_08;
621
    pCmdBlock->configure.configData[ 9] = CONFIG_BYTE_09;
622
    pCmdBlock->configure.configData[10] = CONFIG_BYTE_10 | loopBackMode;
623
    pCmdBlock->configure.configData[11] = CONFIG_BYTE_11;
624
    pCmdBlock->configure.configData[12] = CONFIG_BYTE_12;
625
    pCmdBlock->configure.configData[13] = CONFIG_BYTE_13;
626
    pCmdBlock->configure.configData[14] = CONFIG_BYTE_14;
627
    pCmdBlock->configure.configData[15] = CONFIG_BYTE_15;
628
    pCmdBlock->configure.configData[16] = CONFIG_BYTE_16;
629
    pCmdBlock->configure.configData[17] = CONFIG_BYTE_17;
630
    pCmdBlock->configure.configData[18] = CONFIG_BYTE_18;
631
 
632
    if (link_speed == SPEED_100M)
633
        pCmdBlock->configure.configData[19] = CONFIG_BYTE_19_100T;
634
    else {
635
        pCmdBlock->configure.configData[19] = CONFIG_BYTE_19_10T;
636
        pCmdBlock->configure.configData[20] = CONFIG_BYTE_20;
637
        pCmdBlock->configure.configData[21] = CONFIG_BYTE_21;
638
    }
639
 
640
    sendCommand (CU_START, RU_NOP, ((UINT32)pCmdBlock));
641
 
642
    if ((waitForInt() == ERROR) || (pCmdBlock->configure.ok != 1)) {
643
        printf ("failed.  Status: 0x%04X.\n", pSCB->cmdStat.words.status);
644
        return (ERROR);
645
    }
646
 
647
    initPHY (phy_id, loopBackMode);  /* set up the PHY interface appropriately */
648
 
649
    printf ("done.\n");
650
    return (OK);
651
}
652
 
653
 
654
static int i557RUStart (void)
655
{
656
    volatile long delay;
657
 
658
    memset((char *) pRfd, 0, sizeof(struct rfd));
659
 
660
    /* Set end-of-list bit in the rfd so we don't fall off the end */
661
    pRfd->el = END_OF_LIST;
662
    pRfd->s = 1;
663
    pRfd->sf = 0;                                /* Simplified mode */
664
    pRfd->rbdAddr = (UINT8 *) 0xffffffff;       /* No RBD */
665
    /* buffer size: */
666
    pRfd->size = sizeof (pRfd->rxData) + sizeof (pRfd->destAddr) + sizeof (pRfd->sourceAddr) + sizeof (pRfd->length);
667
 
668
    sendCommand (CU_NOP, RU_START, ((UINT32)pRfd));
669
 
670
    /*
671
     * Poll, can't use waitForInt (), as this step doesn't generate interrupts.
672
     */
673
 
674
    i557Status = 0;
675
 
676
    /* Wait for timeout (i557Status changes) or RU_STAT is RU_READY */
677
    for (delay = 0; (delay < MAX_DELAY) && (pSCB->cmdStat.bits.rus != RU_READY); delay++)
678
        ;       /* Wait... */
679
 
680
    if (pSCB->cmdStat.bits.rus != RU_READY) {
681
        printf ("failed.  Status: 0x%04X.\n", pSCB->cmdStat.words.status);
682
        return (ERROR);
683
    }
684
 
685
    return (OK);
686
}
687
 
688
 
689
/*
690
 * Get packet ready to send out over the network.  Buffer should be
691
 * ETHERMTU + sizeof(enet_addr) + sizeof(UINT16)
692
 */
693
static void setUpPacket (char *pBuf)/* Where to put it */
694
{
695
    memcpy (pBuf, node_address, sizeof(node_address));
696
    pBuf += sizeof(node_address); /* skip dest. address */
697
 
698
    *((UINT16 *) pBuf) = 0;
699
    pBuf += sizeof(UINT16);      /* skip length field */
700
 
701
    makePacket (pBuf, ETHERMTU);
702
}
703
 
704
 
705
/* Send and verify a packet using the current loopback mode. */
706
static int txPacket (char *pBuf) /* Dest addr, ethertype, buffer */
707
{
708
    int status = OK;
709
 
710
    /* Set up transmit command block and execute */
711
    memset((char *) pCmdBlock, 0, sizeof(union cmdBlock));
712
    pCmdBlock->transmit.code = TRANSMIT;
713
    pCmdBlock->transmit.el = END_OF_LIST;
714
    pCmdBlock->transmit.sf = 0;                          /* Simplified mode */
715
    pCmdBlock->transmit.tbdAddr = (UINT8 *) 0xffffffff; /* No TBD */
716
    pCmdBlock->transmit.eof = 1;                        /* Entire frame here */
717
    /* # bytes to tx: */
718
    pCmdBlock->transmit.tcbCount = sizeof (pCmdBlock->transmit.destAddr) + sizeof (pCmdBlock->transmit.length) +
719
        sizeof (pCmdBlock->transmit.txData);
720
 
721
#if 0
722
    printf ("destAddr size = %d\n", sizeof (pCmdBlock->transmit.destAddr));
723
    printf ("length size = %d\n", sizeof (pCmdBlock->transmit.length));
724
    printf ("Transmitting %d bytes\n", pCmdBlock->transmit.tcbCount);
725
#endif
726
 
727
    memcpy (pCmdBlock->transmit.destAddr, pBuf, sizeof(node_address) + sizeof(UINT16) + ETHERMTU);
728
 
729
    rxSem = 0;   /* no Receive interrupt */
730
 
731
    sendCommand (CU_START, RU_NOP, ((UINT32)pCmdBlock));
732
 
733
    if (waitForInt() == ERROR) {
734
        printf ("No Transmit Interrupt\n");
735
        status = ERROR;
736
    }
737
 
738
    if (pCmdBlock->transmit.ok != 1) {
739
        printf ("tx failed.  Status: 0x%04X.\n",
740
                pSCB->cmdStat.words.status);
741
        status = ERROR;
742
    }
743
 
744
    if (status == ERROR) {
745
        printf ("Transmit OK = %d\n", pCmdBlock->transmit.ok);
746
        return (ERROR);
747
    }
748
 
749
#if 1
750
    if (waitForRxInt() == ERROR) {
751
        printf ("No Receive Interrupt\n");
752
        status = ERROR;
753
    }
754
 
755
    if (pRfd->ok != 1) {
756
        printf ("rx failed.  Status: 0x%04X.\n", pSCB->cmdStat.words.status);
757
        status = ERROR;
758
    }
759
 
760
#if 1
761
    /* If RU still ready, hang for receive interrupt */
762
    if (pSCB->cmdStat.bits.rus == RU_READY)     {
763
        if (waitForRxInt() == ERROR)  {
764
            printf ("No Receive Interrupt\n");
765
            status = ERROR;
766
        }
767
 
768
        if (pRfd->ok != 1) {
769
            printf ("rx failed.  Status: 0x%04X.\n", pSCB->cmdStat.words.status);
770
            status = ERROR;
771
        }
772
    }
773
#endif
774
 
775
    if (status == ERROR) {
776
        printf ("\nTransmit Stats:\n");
777
        printf ("---------------\n");
778
        printf ("Transmit OK = %d\n", pCmdBlock->transmit.ok);
779
 
780
        printf ("\nReceive Stats:\n");
781
        printf ("---------------\n\n");
782
        printf ("Receive OK = %d\n", pRfd->ok);
783
        printf ("CRC Error = %d\n", pRfd->crcErr);
784
        printf ("Alignment Error = %d\n", pRfd->alignErr);
785
        printf ("Resource Error = %d\n", pRfd->noRsrc);
786
        printf ("DMA Overrun Error = %d\n", pRfd->dmaOverrun);
787
        printf ("Frame Too Short Error = %d\n", pRfd->frameTooshort);
788
        printf ("Receive Collision Error = %d\n", pRfd->rxColl);
789
        return (ERROR);
790
    }
791
 
792
#if 0
793
    printf ("Packet Actual Size = %d\n", pRfd->actCount);
794
#endif
795
 
796
    if (checkPacket (pCmdBlock->transmit.txData, pRfd->rxData, ETHERMTU) == ERROR) {
797
        printf ("data verify error.\n");
798
        return (ERROR);
799
    }
800
 
801
    if (forever_flag == FALSE)
802
        printf ("data OK.\n");
803
#endif
804
 
805
    return (OK);
806
}
807
 
808
 
809
/*
810
 * "Poor Man's Malloc" - return a pointer to a block of memory at least
811
 * The block returned will have been zeroed.
812
 */
813
static char *malloc (int numBytes) /* number of bytes needed */
814
{
815
    volatile char *rtnPtr;      /* ptr to return to caller */
816
    long        new_mem_pool;   /* For figuring new pool base address */
817
 
818
    rtnPtr = mem_pool;  /* Return pointer to start of free pool */
819
 
820
    /* Now calculate new base of free memory pool (round to >= 16 bytes) */
821
    new_mem_pool = (UINT32) mem_pool;
822
    new_mem_pool = ((new_mem_pool + numBytes + 0x10) & (~((UINT32) 0x0f)));
823
    mem_pool = (volatile char *) new_mem_pool;
824
 
825
    memset(rtnPtr, 0, numBytes);
826
 
827
    return ((char *) rtnPtr);
828
}
829
 
830
 
831
/*
832
 * Write "value" to PORT register of PRO/100.
833
 */
834
static void portWrite (UINT32 value)
835
{
836
    *PORT_REG(adapter[0]) = value;
837
}
838
 
839
 
840
/******************************************************************************
841
*
842
* sendCommand - send a command to the 82557 via the on-chip SCB
843
*
844
* Send a command to the 82557.  On the 82557, the Channel Attention signal
845
* has been replaced by an on-chip SCB.  Accesses to the Command Word portion
846
* of the SCB automatically forces the '557 to look at the various data
847
* structures which make up its interface.
848
*/
849
static void sendCommand (UINT8 cuc, UINT8 ruc, UINT32 scb_general_ptr)
850
{
851
    register CMD_STAT_U temp_cmdStat;
852
    volatile union cmdBlock *pBlock = (union cmdBlock *)scb_general_ptr;
853
    volatile int loop_ctr;
854
 
855
    /* Mask adapter interrupts to prevent the interrupt handler from
856
       playing with the SCB */
857
    mask_557_ints();
858
 
859
    /* must wait for the Command Unit to become idle to prevent
860
       us from issueing a CU_START to an active Command Unit */
861
    for (loop_ctr = BUSY_WAIT_LIMIT; loop_ctr > 0; loop_ctr--) {
862
        if ((pSCB->cmdStat.words.status & SCB_S_CUMASK) == SCB_S_CUIDLE)
863
            break;
864
    }
865
    if (loop_ctr == 0) {
866
        printf("sendCommand: CU won't go idle, command ignored\n");
867
        unmask_557_ints();
868
        return;
869
    }
870
 
871
    /* when setting the command word, read the current word from
872
       the SCB and preserve the upper byte which contains the interrupt
873
       mask bit */
874
    temp_cmdStat.words.command = (pSCB->cmdStat.words.command & 0xff00);
875
    temp_cmdStat.words.status = 0;
876
 
877
    /* set up the Command and Receive unit commands */
878
    temp_cmdStat.bits.cuc = cuc & 0x07;
879
    temp_cmdStat.bits.ruc = ruc & 0x07;
880
 
881
    /* Clear flag */
882
    waitSem = 0;
883
 
884
    /* write the General Pointer portion of the SCB first */
885
    pSCB->scb_general_ptr = scb_general_ptr;
886
 
887
    /* write the Command Word of the SCB */
888
    pSCB->cmdStat.words.command = temp_cmdStat.words.command;
889
 
890
    /* only wait for command which will complete immediately */
891
    if ((scb_general_ptr != 0/* NULL*/) && (ruc != RU_START)) {
892
        /* wait for command acceptance and completion */
893
        for (loop_ctr = BUSY_WAIT_LIMIT; loop_ctr > 0; loop_ctr--) {
894
            if ((pSCB->cmdStat.bits.cuc == 0) && (pBlock->nop.c == 1))
895
                break;
896
        }
897
        if (loop_ctr == 0) {
898
            printf("sendCommand: Timeout on command complete\n");
899
            printf("Cmd Complete bit = %02X\n", pBlock->nop.c);
900
            printf("CU command       = 0x%02X\n", cuc);
901
            printf("RU command       = 0x%02X\n", ruc);
902
            printf("SCB Gen Ptr      = 0x%X\n", scb_general_ptr);
903
            printf("scb status       = 0x%04X\n", pSCB->cmdStat.words.status);
904
            printf("scb command      = 0x%04X\n", pSCB->cmdStat.words.command);
905
        }
906
    }
907
 
908
#if 0
909
    /* DEBUG */
910
    printf("scb command = 0x%04X\n", pSCB->cmdStat.words.command);
911
    printf("scb status  = 0x%04X\n", pSCB->cmdStat.words.status);
912
#endif
913
 
914
    unmask_557_ints();
915
    return;
916
}
917
 
918
 
919
/*
920
 * Do a port reset on 82557.
921
 */
922
static void resetChip (void)
923
{
924
    portWrite (PORT_RESET);     /* bits 4-31 not used for reset */
925
 
926
    /* wait 5 msec for device to stabilize */
927
    delay_ms(5);
928
}
929
 
930
 
931
/*
932
 * Setup contents of a packet.
933
 */
934
static void makePacket (UINT8 *pPacket, int length)
935
{
936
    int byteNum;        /* Current byte number */
937
 
938
    for (byteNum = 0; byteNum < length; byteNum++)
939
        *pPacket++ = byteNum + ' ';
940
}
941
 
942
 
943
/*
944
 * Verify contents of a received packet to what was transmitted.
945
 * Returns OK if they match, ERROR if not.
946
 */
947
static int checkPacket (UINT8 *pTxBuffer, UINT8 *pRxBuffer, int length)
948
{
949
    int byteNum;        /* Current byte number */
950
 
951
     for (byteNum = 0; byteNum < length; byteNum++) {
952
         if (*pTxBuffer++ != *pRxBuffer++) {
953
             printf("Error at byte 0x%x\n", byteNum);
954
             printf("Expected 0x%02X, got 0x%02X\n", *(pTxBuffer - 1), *(pRxBuffer - 1));
955
             return (ERROR);
956
         }
957
     }
958
     return (OK);
959
}
960
 
961
 
962
/*
963
 * Interrupt handler for i82557.  It acknowledges the interrupt
964
 * by setting the ACK bits in the command word and issuing a
965
 * channel attention.  It then updates the global status variable
966
 * and gives the semaphore to wake up the main routine.
967
 */
968
int i557IntHandler (int arg)  /* should return int */
969
{
970
    register CMD_STAT_U temp_cmdStat;
971
    register int rxFlag = FALSE;
972
 
973
    temp_cmdStat.words.status = pSCB->cmdStat.words.status;
974
 
975
    /* check to see if it was the PRO/100 */
976
    if (temp_cmdStat.words.status & I557_INT) {
977
        /* Wait for command word to clear - indicates no pending commands */
978
        while (pSCB->cmdStat.words.command)
979
            ;
980
 
981
        /* Update global status variable */
982
        i557Status = temp_cmdStat.words.status;
983
 
984
        /* If the interrupt was due to a received frame... */
985
        if (temp_cmdStat.bits.statack_fr)
986
            rxFlag = TRUE;
987
 
988
        temp_cmdStat.words.status = temp_cmdStat.words.status & I557_INT;
989
 
990
        /* Acknowledge interrupt by setting ack bits */
991
        pSCB->cmdStat.words.status = temp_cmdStat.words.status;
992
 
993
        /* Wait for command word to clear - indicates IACK accepted */
994
        while (pSCB->cmdStat.words.command)
995
            ;
996
 
997
        /* Update global status variable and unblock task */
998
        waitSem = 1;
999
 
1000
        if (rxFlag == TRUE)
1001
            rxSem = 1;
1002
 
1003
        return(1);              /* serviced - return 1 */
1004
    }
1005
    return(0);                   /* nothing serviced - return 0 */
1006
}
1007
 
1008
 
1009
 
1010
/*
1011
 * Take the semaphore and block until i557 interrupt or timeout.
1012
 * Returns OK if an interrupt occured, ERROR if a timeout.
1013
 */
1014
static int waitForInt(void)
1015
{
1016
    int num_ms = 0;
1017
 
1018
    while ((waitSem == 0) && (num_ms != 2000)) { /* wait max 2secs for the interrupt */
1019
        delay_ms(1);
1020
        num_ms++;
1021
    }
1022
 
1023
    if (!waitSem) {
1024
        printf("Wait error!\n");
1025
        return (ERROR);
1026
    } else
1027
        return (OK);
1028
}
1029
 
1030
 
1031
static int waitForRxInt(void)
1032
{
1033
    int num_ms = 0;
1034
 
1035
    while ((rxSem == 0) && (num_ms != 2000)) { /* wait max 2secs for the interrupt */
1036
        delay_ms(1);
1037
        num_ms++;
1038
    }
1039
 
1040
    if (!rxSem) {
1041
        printf("Rx Wait error!\n");
1042
        return (ERROR);
1043
    } else
1044
        return (OK);
1045
}
1046
 
1047
 
1048
static UINT16 readMDI (int unit, UINT8  phyAdd, UINT8   regAdd)
1049
{
1050
    register MDI_CONTROL_U mdiCtrl;
1051
    int num_ms = 0;
1052
 
1053
    /* prepare for the MDI operation */
1054
    mdiCtrl.bits.ready = MDI_NOT_READY;
1055
    mdiCtrl.bits.intEnab = MDI_POLLED;  /* no interrupts */
1056
    mdiCtrl.bits.op = MDI_READ_OP;
1057
    mdiCtrl.bits.phyAdd = phyAdd & 0x1f;
1058
    mdiCtrl.bits.regAdd = regAdd & 0x1f;
1059
 
1060
    /* start the operation */
1061
    *MDI_CTL_REG(adapter[unit]) = mdiCtrl.word;
1062
 
1063
    /* delay a bit */
1064
    delay_ms(1);
1065
 
1066
    /* poll for completion */
1067
    mdiCtrl.word = *MDI_CTL_REG(adapter[unit]);
1068
 
1069
    while ((mdiCtrl.bits.ready == MDI_NOT_READY) && (num_ms != 2000)) { /* wait max 2secs */
1070
        mdiCtrl.word = *MDI_CTL_REG(adapter[unit]);
1071
        delay_ms(1);
1072
        num_ms++;
1073
    }
1074
 
1075
    if (num_ms >= 2000) {
1076
        printf ("readMDI Timeout!\n");
1077
        return (-1);
1078
    } else
1079
        return ((UINT16)mdiCtrl.bits.data);
1080
}
1081
 
1082
 
1083
static void writeMDI (int unit, UINT8 phyAdd, UINT8 regAdd, UINT16 data)
1084
{
1085
    register MDI_CONTROL_U mdiCtrl;
1086
    int num_ms = 0;
1087
 
1088
    /* prepare for the MDI operation */
1089
    mdiCtrl.bits.ready = MDI_NOT_READY;
1090
    mdiCtrl.bits.intEnab = MDI_POLLED;  /* no interrupts */
1091
    mdiCtrl.bits.op = MDI_WRITE_OP;
1092
    mdiCtrl.bits.phyAdd = phyAdd & 0x1f;
1093
    mdiCtrl.bits.regAdd = regAdd & 0x1f;
1094
    mdiCtrl.bits.data = data & 0xffff;
1095
 
1096
    /* start the operation */
1097
    *MDI_CTL_REG(adapter[unit]) = mdiCtrl.word;
1098
 
1099
    /* delay a bit */
1100
    delay_ms(1);
1101
 
1102
    /* poll for completion */
1103
    mdiCtrl.word = *MDI_CTL_REG(adapter[unit]);
1104
 
1105
    while ((mdiCtrl.bits.ready == MDI_NOT_READY) && (num_ms != 2000)) {
1106
        mdiCtrl.word = *MDI_CTL_REG(adapter[unit]);
1107
        delay_ms(1);
1108
        num_ms++;
1109
    }
1110
    if (num_ms >= 2000)
1111
        printf ("writeMDI Timeout!\n");
1112
 
1113
    return;
1114
}
1115
 
1116
static int get_ether_addr (int     unit,
1117
                           UINT8   *buffer,
1118
                           int     print_flag)  /* TRUE to print the information */
1119
{
1120
    UINT16 temp_node_addr[3] = {0,0,0};
1121
    register int i;
1122
 
1123
    /* Get the adapter's node address */
1124
    if (eeprom_read (adapter[unit],IA_OFFSET,temp_node_addr,3) != OK) {
1125
        printf ("Error reading the IA address from Serial EEPROM.\n");
1126
        return (ERROR);
1127
    }
1128
 
1129
    buffer[0] = (UINT8)(temp_node_addr[0] & 0x00ff);
1130
    buffer[1] = (UINT8)((temp_node_addr[0] & 0xff00)>>8);
1131
    buffer[2] = (UINT8)(temp_node_addr[1] & 0x00ff);
1132
    buffer[3] = (UINT8)((temp_node_addr[1] & 0xff00)>>8);
1133
    buffer[4] = (UINT8)(temp_node_addr[2] & 0x00ff);
1134
    buffer[5] = (UINT8)((temp_node_addr[2] & 0xff00)>>8);
1135
 
1136
    if (print_flag == TRUE) {
1137
        printf("Ethernet Address = [ ");
1138
        for (i=0; i<6; i++) {
1139
            printf("0x%02X ", buffer[i]);
1140
        }
1141
        printf("]\n\n");
1142
    }
1143
    return (OK);
1144
}
1145
 

powered by: WebSVN 2.1.0

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