]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/hal/arm/xscale/iq80310/v2_0/src/diag/ether_test.c
Initial revision
[karo-tx-redboot.git] / packages / hal / arm / xscale / iq80310 / v2_0 / src / diag / ether_test.c
1 //=============================================================================
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