1 //=============================================================================
3 // ether_test.c - Cyclone Diagnostics
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.
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.
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
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.
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.
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.
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####
41 // Author(s): Scott Coulter, Jeff Frazier, Eric Breeden
47 //####DESCRIPTIONEND####
49 //===========================================================================*/
51 #include <cyg/io/pci_hw.h>
52 #include <cyg/io/pci.h>
55 #include "ether_test.h"
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);
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);
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 */
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 */
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;*/
99 static int forever_flag = FALSE;
100 static UINT32 phy_id = 0;
102 /* 82557 required data structures which must be allocated */
103 static struct rfd *pRfd;
104 static union cmdBlock *pCmdBlock;
105 static char *pPacketBuf;
107 #define SPEED_NOLINK 0
109 #define SPEED_100M 100
110 static int link_speed = SPEED_NOLINK;
113 int unit_devno, unit_busno, unit_funcno;
115 #define BUSY_WAIT_LIMIT 0xf000 /* the upper limit on a busy wait
116 for command completion, etc. */
118 static void mask_557_ints (void)
120 pSCB->cmdStat.bits.m = 1;
123 static void unmask_557_ints (void)
125 pSCB->cmdStat.bits.m = 0;
128 /*****************************************************************************
129 * pci_ether_test - i8255x PCI Ethernet test
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.
136 void pci_ether_test (UINT32 busno, UINT32 devno, UINT32 funcno)
140 int broadcom_flag = FALSE;
141 UINT16 phy_addr_reg, temp1, temp2;
142 cyg_pci_device_id devid;
146 devid = CYG_PCI_DEV_MAKE_ID(busno, CYG_PCI_DEV_MAKE_DEVFN(devno,funcno));
148 /* read the PCI BAR for the Ethernet controller */
149 cyg_pci_read_config_uint32(devid, 0x10, &adapter[0]);
151 /* strip off BAR indicator bits */
152 adapter[0] &= 0xfffffff0;
156 unit_funcno = funcno;
158 /* pointer to on-chip SCB */
159 pSCB = (struct SCBtype *)(adapter[0] + SCB_OFFSET);
163 printf ("PCI Base Address = 0x%X\n", adapter[0]);
164 printf ("PCI Interrupt Pin = 0x%02X\n", unit_intpin);
166 /* Initialize malloc's memory pool pointer */
167 mem_pool = (char *) ETHER_MEM_POOL;
169 /* Start the timer for delay implementation
170 printf("Starting timer... ");
172 printf("Done.\n Resetting chip... ");
174 /* reset the 82557 to start with a clean slate */
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");
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);
188 if ((phy_id & 0xfffffff0) == I82555_PHY_ID) {
189 printf ("Intel 82555/558 PHY detected...\n");
191 /* dummy read for reliable status */
192 (void)readMDI (0, MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT);
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");
197 phy_addr_reg = readMDI (0, MDI_DEFAULT_PHY_ADDR, I82555_STATCTRL_REG);
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;
203 printf ("Connect Speed is NOT VALID\n");
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));
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");
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;
220 printf ("Connect Speed is NOT VALID\n");
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));
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");
232 phy_addr_reg = readMDI (0 ,MDI_DEFAULT_PHY_ADDR, DP83840_PHY_ADDR_REG);
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;
238 else printf ("Connect Speed is NOT VALID\n");
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;
247 if (phy_id == I82553_REVAB_PHY_ID) {
248 printf ("Intel 82553 PHY detected...\n");
249 printf ("Revision = B\n");
250 broadcom_flag = TRUE;
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));
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");
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;
266 printf ("Connect Speed is NOT VALID\n");
270 /* Run the built-in self test through the port register */
271 if (i557SelfTest () == ERROR) {
272 mask_557_ints (); /* Disable 557 interrupt */
276 /* Reset clears the interrupt mask */
279 printf ("Press return to initialize ethernet controller.\n");
282 /* Initialize data structures */
283 if (i557Init () == ERROR) {
284 mask_557_ints (); /* Disable 557 interrupt */
288 /* Set hardware address */
289 if (i557AddrSet () == ERROR) {
290 mask_557_ints (); /* Disable 557 interrupt */
294 printf ("Press return to perform internal loopback test.\n");
297 /* Configure for internal loopback */
298 if (i557Config (INT_LOOP_BACK) == ERROR) {
299 mask_557_ints (); /* Disable 557 interrupt */
305 /* Initialize receive buffer and enable receiver */
306 if (i557RUStart () == ERROR) {
307 mask_557_ints (); /* Disable 557 interrupt */
312 setUpPacket (pPacketBuf);
313 if (txPacket (pPacketBuf) == ERROR) {
314 mask_557_ints (); /* Disable 557 interrupt */
318 printf ("Press return to perform loopback through PHY.\n");
321 /* Configure for external loopback */
322 if (i557Config (EXT_LOOP_BACK) == ERROR) {
323 mask_557_ints (); /* Disable 557 interrupt */
329 /* Initialize receive buffer and enable receiver */
330 if (i557RUStart () == ERROR) {
331 mask_557_ints (); /* Disable 557 interrupt */
336 setUpPacket (pPacketBuf);
337 if (txPacket (pPacketBuf) == ERROR) {
338 mask_557_ints (); /* Disable 557 interrupt */
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");
349 printf ("Enter the number of times to run test (0 = forever): ");
353 if (i557RUStart () == ERROR) {
354 mask_557_ints (); /* Disable 557 interrupt */
358 setUpPacket (pPacketBuf);
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 */
373 if (((count) % 1000) == 0)
374 printf("Loopback Cycle Count = %d\n", count);
377 forever_flag = FALSE;
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 */
389 printf("Loopback Cycle Count = %d\n", count);
394 mask_557_ints (); /* Disable 557 interrupt */
396 printf ("\nEthernet controller passed. Press return to continue.\n");
403 /* Perform internal self test - returns OK if sucessful, ERROR if not. */
404 static int i557SelfTest ()
406 volatile struct selfTest *pSelfTestMem;
412 /* reset the 82557 to start with a clean slate */
415 /* Allocate some memory for the self test */
416 pSelfTestMem = (struct selfTest *) malloc (sizeof(struct selfTest));
418 if (pSelfTestMem == NULL) {
419 printf ("Couldn't get memory for self test.\n");
423 printf ("Sending PORT* self-test command...\n");
424 printf ("Local Dump address = 0x%X\n", pSelfTestMem);
426 /* Set all bits in second word, wait until it changes or a timeout */
427 pSelfTestMem->u.word2 = ~0;
428 oldWord2 = pSelfTestMem->u.word2;
430 temp = ((UINT32) pSelfTestMem) + PORT_SELF_TEST;
434 /* Wait for test completion or for timeout */
435 for (delay = 0; (delay < MAX_DELAY) && (pSelfTestMem->u.word2 == oldWord2); delay++)
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);
445 rtnVal = pSelfTestMem->u.bits.selfTest ? ERROR : OK;
451 /* Initialize the 82557. */
452 static int i557Init (void)
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");
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;
466 /* Reset chip and initialize */
467 printf ("Initializing... ");
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);
476 /* Initialize interrupts */
478 /* if it is the onboard i82559, it does not use the conventional PCI
479 interrupt routines because the interrupt is not multiplexed onto
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");
486 if (enable_external_interrupt (ENET_INT_ID) != OK) {
487 printf ("Error enabling Ethernet interrupt!\n");
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");
502 static int initPHY (UINT32 device_type, int loop_mode)
507 /* strip off revision and phy. id information */
508 revision = (UINT8)(device_type & REVISION_MASK);
509 device_type &= ~REVISION_MASK;
511 switch (device_type) {
513 temp_reg = readMDI (0, MDI_DEFAULT_PHY_ADDR, MDI_PHY_CTRL); /* get ready for loopback setting */
516 case EXT_LOOP_BACK: /* loopback on the MII interface */
517 temp_reg |= MDI_CTRL_LOOPBACK; /* MII loopback */
525 writeMDI(0, MDI_DEFAULT_PHY_ADDR, MDI_PHY_CTRL, temp_reg);
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);
533 /* get ready for loopback setting */
534 temp_reg = readMDI (0,MDI_DEFAULT_PHY_ADDR, DP83840_LOOPBACK_REG);
535 temp_reg &= CLEAR_LOOP_BITS;
539 temp_reg |= TWISTER_LOOPBACK;
547 writeMDI (0,MDI_DEFAULT_PHY_ADDR, DP83840_LOOPBACK_REG, temp_reg);
551 case I82553_REVAB_PHY_ID:
564 /* Set hardware address of the 82557. */
565 static int i557AddrSet ()
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]);
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));
577 sendCommand (CU_START, RU_NOP, ((UINT32)pCmdBlock));
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);
591 /* Configure the 82557. */
592 static int i557Config (UINT8 loopBackMode) /* None, int, or ext 1, 2 (see etherTest.h) */
594 printf ("\nConfiguring for ");
596 switch (loopBackMode) {
598 printf ("internal loopback... ");
601 printf ("external loopback, LPBK* active... ");
604 printf ("Unknown loopback mode, exiting...\n");
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;
632 if (link_speed == SPEED_100M)
633 pCmdBlock->configure.configData[19] = CONFIG_BYTE_19_100T;
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;
640 sendCommand (CU_START, RU_NOP, ((UINT32)pCmdBlock));
642 if ((waitForInt() == ERROR) || (pCmdBlock->configure.ok != 1)) {
643 printf ("failed. Status: 0x%04X.\n", pSCB->cmdStat.words.status);
647 initPHY (phy_id, loopBackMode); /* set up the PHY interface appropriately */
654 static int i557RUStart (void)
658 memset((char *) pRfd, 0, sizeof(struct rfd));
660 /* Set end-of-list bit in the rfd so we don't fall off the end */
661 pRfd->el = END_OF_LIST;
663 pRfd->sf = 0; /* Simplified mode */
664 pRfd->rbdAddr = (UINT8 *) 0xffffffff; /* No RBD */
666 pRfd->size = sizeof (pRfd->rxData) + sizeof (pRfd->destAddr) + sizeof (pRfd->sourceAddr) + sizeof (pRfd->length);
668 sendCommand (CU_NOP, RU_START, ((UINT32)pRfd));
671 * Poll, can't use waitForInt (), as this step doesn't generate interrupts.
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++)
680 if (pSCB->cmdStat.bits.rus != RU_READY) {
681 printf ("failed. Status: 0x%04X.\n", pSCB->cmdStat.words.status);
690 * Get packet ready to send out over the network. Buffer should be
691 * ETHERMTU + sizeof(enet_addr) + sizeof(UINT16)
693 static void setUpPacket (char *pBuf)/* Where to put it */
695 memcpy (pBuf, node_address, sizeof(node_address));
696 pBuf += sizeof(node_address); /* skip dest. address */
698 *((UINT16 *) pBuf) = 0;
699 pBuf += sizeof(UINT16); /* skip length field */
701 makePacket (pBuf, ETHERMTU);
705 /* Send and verify a packet using the current loopback mode. */
706 static int txPacket (char *pBuf) /* Dest addr, ethertype, buffer */
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 */
718 pCmdBlock->transmit.tcbCount = sizeof (pCmdBlock->transmit.destAddr) + sizeof (pCmdBlock->transmit.length) +
719 sizeof (pCmdBlock->transmit.txData);
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);
727 memcpy (pCmdBlock->transmit.destAddr, pBuf, sizeof(node_address) + sizeof(UINT16) + ETHERMTU);
729 rxSem = 0; /* no Receive interrupt */
731 sendCommand (CU_START, RU_NOP, ((UINT32)pCmdBlock));
733 if (waitForInt() == ERROR) {
734 printf ("No Transmit Interrupt\n");
738 if (pCmdBlock->transmit.ok != 1) {
739 printf ("tx failed. Status: 0x%04X.\n",
740 pSCB->cmdStat.words.status);
744 if (status == ERROR) {
745 printf ("Transmit OK = %d\n", pCmdBlock->transmit.ok);
750 if (waitForRxInt() == ERROR) {
751 printf ("No Receive Interrupt\n");
756 printf ("rx failed. Status: 0x%04X.\n", pSCB->cmdStat.words.status);
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");
769 printf ("rx failed. Status: 0x%04X.\n", pSCB->cmdStat.words.status);
775 if (status == ERROR) {
776 printf ("\nTransmit Stats:\n");
777 printf ("---------------\n");
778 printf ("Transmit OK = %d\n", pCmdBlock->transmit.ok);
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);
793 printf ("Packet Actual Size = %d\n", pRfd->actCount);
796 if (checkPacket (pCmdBlock->transmit.txData, pRfd->rxData, ETHERMTU) == ERROR) {
797 printf ("data verify error.\n");
801 if (forever_flag == FALSE)
802 printf ("data OK.\n");
810 * "Poor Man's Malloc" - return a pointer to a block of memory at least
811 * The block returned will have been zeroed.
813 static char *malloc (int numBytes) /* number of bytes needed */
815 volatile char *rtnPtr; /* ptr to return to caller */
816 long new_mem_pool; /* For figuring new pool base address */
818 rtnPtr = mem_pool; /* Return pointer to start of free pool */
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;
825 memset(rtnPtr, 0, numBytes);
827 return ((char *) rtnPtr);
832 * Write "value" to PORT register of PRO/100.
834 static void portWrite (UINT32 value)
836 *PORT_REG(adapter[0]) = value;
840 /******************************************************************************
842 * sendCommand - send a command to the 82557 via the on-chip SCB
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.
849 static void sendCommand (UINT8 cuc, UINT8 ruc, UINT32 scb_general_ptr)
851 register CMD_STAT_U temp_cmdStat;
852 volatile union cmdBlock *pBlock = (union cmdBlock *)scb_general_ptr;
853 volatile int loop_ctr;
855 /* Mask adapter interrupts to prevent the interrupt handler from
856 playing with the SCB */
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)
866 printf("sendCommand: CU won't go idle, command ignored\n");
871 /* when setting the command word, read the current word from
872 the SCB and preserve the upper byte which contains the interrupt
874 temp_cmdStat.words.command = (pSCB->cmdStat.words.command & 0xff00);
875 temp_cmdStat.words.status = 0;
877 /* set up the Command and Receive unit commands */
878 temp_cmdStat.bits.cuc = cuc & 0x07;
879 temp_cmdStat.bits.ruc = ruc & 0x07;
884 /* write the General Pointer portion of the SCB first */
885 pSCB->scb_general_ptr = scb_general_ptr;
887 /* write the Command Word of the SCB */
888 pSCB->cmdStat.words.command = temp_cmdStat.words.command;
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))
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);
910 printf("scb command = 0x%04X\n", pSCB->cmdStat.words.command);
911 printf("scb status = 0x%04X\n", pSCB->cmdStat.words.status);
920 * Do a port reset on 82557.
922 static void resetChip (void)
924 portWrite (PORT_RESET); /* bits 4-31 not used for reset */
926 /* wait 5 msec for device to stabilize */
932 * Setup contents of a packet.
934 static void makePacket (UINT8 *pPacket, int length)
936 int byteNum; /* Current byte number */
938 for (byteNum = 0; byteNum < length; byteNum++)
939 *pPacket++ = byteNum + ' ';
944 * Verify contents of a received packet to what was transmitted.
945 * Returns OK if they match, ERROR if not.
947 static int checkPacket (UINT8 *pTxBuffer, UINT8 *pRxBuffer, int length)
949 int byteNum; /* Current byte number */
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));
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.
968 int i557IntHandler (int arg) /* should return int */
970 register CMD_STAT_U temp_cmdStat;
971 register int rxFlag = FALSE;
973 temp_cmdStat.words.status = pSCB->cmdStat.words.status;
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)
981 /* Update global status variable */
982 i557Status = temp_cmdStat.words.status;
984 /* If the interrupt was due to a received frame... */
985 if (temp_cmdStat.bits.statack_fr)
988 temp_cmdStat.words.status = temp_cmdStat.words.status & I557_INT;
990 /* Acknowledge interrupt by setting ack bits */
991 pSCB->cmdStat.words.status = temp_cmdStat.words.status;
993 /* Wait for command word to clear - indicates IACK accepted */
994 while (pSCB->cmdStat.words.command)
997 /* Update global status variable and unblock task */
1003 return(1); /* serviced - return 1 */
1005 return(0); /* nothing serviced - return 0 */
1011 * Take the semaphore and block until i557 interrupt or timeout.
1012 * Returns OK if an interrupt occured, ERROR if a timeout.
1014 static int waitForInt(void)
1018 while ((waitSem == 0) && (num_ms != 2000)) { /* wait max 2secs for the interrupt */
1024 printf("Wait error!\n");
1031 static int waitForRxInt(void)
1035 while ((rxSem == 0) && (num_ms != 2000)) { /* wait max 2secs for the interrupt */
1041 printf("Rx Wait error!\n");
1048 static UINT16 readMDI (int unit, UINT8 phyAdd, UINT8 regAdd)
1050 register MDI_CONTROL_U mdiCtrl;
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;
1060 /* start the operation */
1061 *MDI_CTL_REG(adapter[unit]) = mdiCtrl.word;
1066 /* poll for completion */
1067 mdiCtrl.word = *MDI_CTL_REG(adapter[unit]);
1069 while ((mdiCtrl.bits.ready == MDI_NOT_READY) && (num_ms != 2000)) { /* wait max 2secs */
1070 mdiCtrl.word = *MDI_CTL_REG(adapter[unit]);
1075 if (num_ms >= 2000) {
1076 printf ("readMDI Timeout!\n");
1079 return ((UINT16)mdiCtrl.bits.data);
1083 static void writeMDI (int unit, UINT8 phyAdd, UINT8 regAdd, UINT16 data)
1085 register MDI_CONTROL_U mdiCtrl;
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;
1096 /* start the operation */
1097 *MDI_CTL_REG(adapter[unit]) = mdiCtrl.word;
1102 /* poll for completion */
1103 mdiCtrl.word = *MDI_CTL_REG(adapter[unit]);
1105 while ((mdiCtrl.bits.ready == MDI_NOT_READY) && (num_ms != 2000)) {
1106 mdiCtrl.word = *MDI_CTL_REG(adapter[unit]);
1111 printf ("writeMDI Timeout!\n");
1116 static int get_ether_addr (int unit,
1118 int print_flag) /* TRUE to print the information */
1120 UINT16 temp_node_addr[3] = {0,0,0};
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");
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);
1136 if (print_flag == TRUE) {
1137 printf("Ethernet Address = [ ");
1138 for (i=0; i<6; i++) {
1139 printf("0x%02X ", buffer[i]);