/* * This is a very simple example of a DR11 interprocessor link using the IKON * model 10103 Sbus or 10116 PCI bus dr11 emulator. It uses the standard interprocessor link * protocol, although without some of the bells and whistles that a robust link * would probably incporate. The strange block size of 0x2002 bytes matches the * block size used at IKON for factory link testing of various DR11 emulators * * This is the master end of the link - it generates a pattern in a buffer, then sends * an attention to the slave end of the link (as a request to send). It waits for * an attention back (clear to send), then sends the data block. It then waits for an * attention from the slave indicating that the slave wants to send the block back. The master * then starts a block read (with an attention at the start of the read previously enabled) * and waits for the data block. The master compares the two buffers, and halts if there is a * data error. If not, the process continues indefinitely, with a changing data pattern. * * In order for handshaking to begin correctly, the slave end of the link must be * started before the master end. * * 4 February, 2004 minor updates for readability * * 5 October, 2005 added includes to keep Linux happy, * converted ioctl arg to __u32 to preserve size in 64 bit mode */ #include #include #include #include #include #include "./idr_io.h" /* will pick up to get __u32 type */ u_short inarray[0x2000], outarray[0x2000]; int i, j, filedes, pass_count; u_short pattern; extern errno; char devname[16]; char devpath[32] = "/dev/\0"; __u32 arg; main() { printf("\nMaster Link Test for IKON 10116/10118 PCI bus DR11-W emulators.\n\n"); printf("This program provides the master end of an interprocessor link test.\n"); printf("When used with the Slave Link Test program running in this or another host,\n"); printf("it allows two IKON DR11-W emulators to be tested in link mode.\n\n"); printf("Link mode requires that two DR11s be connected J1 to J2, and J2 to J1 using\n"); printf("appropriate link cable(s)\n\n"); printf("The master end of the link generates a changing data buffer, which is sent to\n"); printf("the slave end of the link, which returns it. The master compares the buffer\n"); printf("with the buffer received, and flags any errors. This test will thoroughly\n"); printf("exercise and test both boards, and the interconnecting cable, and runs\n"); printf("indefinitely, until terminated with control-C.\n\n"); printf("This version of Link Master operates the board in manual mode - it is intended\n"); printf("as an example of how to use the board and driver in manual mode (see source code)\n\n"); printf("THE SLAVE END OF THE LINK MUST BE STARTED FIRST!!\n\n"); printf("Please enter the name of the device to be tested: (idr0...idr9, quit) "); scanf("%15s", devname); if (strcmp(devname, "quit\0") == 0) exit(0); strcat(devpath, devname); printf("\ntesting device %s\n", devpath); /* * open the device */ if ((filedes = open(devpath, O_RDWR)) == -1) { printf("error on open, errno = %d\n", errno); exit(0); } printf("file descriptor = 0x%x\n", filedes); /* * set to manual mode & set timeout values */ if (ioctl(filedes, IDRIO_MANUAL, &arg) == -1) { printf("error on MANUAL, errno = %d, pass count = %d\n", errno, pass_count); exit(0); } arg = 30; if (ioctl(filedes, IDRIO_SET_ATTN_TIME, &arg) == -1) { printf("error on SET_ATTN_TIME, errno = %d, pass count = %d\n", errno, pass_count); exit(0); } arg = 30; if (ioctl(filedes, IDRIO_SET_RDY_TIME, &arg) == -1) { printf("error on SET_RDY_TIME, errno = %d, pass count = %d\n", errno, pass_count); exit(0); } arg = 30; if (ioctl(filedes, IDRIO_SET_DMA_TIME, &arg) == -1) { printf("error on SET_DMA_TIME, errno = %d, pass count = %d\n", errno, pass_count); exit(0); } /* * loop forever */ while (1) { /* * we must reset the invisible UNIX counter to 0 every so often * at least, we had to with SunOS */ lseek(filedes, (off_t) 0, 0); for (i = 0; i < 100; i++, pass_count++) { /* * generate a pattern * since the buffer size is not a power of two, the pattern in each buffer will * be somewhat different */ for (j = 0; j < 0x1001; j++, pattern++) outarray[j] = pattern; /* * issue a request to send */ arg = IDR_ACF2; if (ioctl(filedes, IDRIO_IMM_PULSE, &arg) == -1) { printf("error at IMM_PULSE, errno = %d, pass count = %d\n", errno, pass_count); exit(0); } /* * wait for clear to send */ if (ioctl(filedes, IDRIO_ATTN_WAIT, &arg) == -1) { printf("error at ATTN_WAIT, errno = %d, pass_count = %d\n", errno, pass_count); exit(0); } /* * do the write in manual mode using two write calls */ arg = 0x1000; if (ioctl(filedes, IDRIO_SET_RANGE, &arg) == -1) { printf("error on set range, errno = %d\n", errno); exit(0); } if (ioctl(filedes, IDRIO_START_WRITE, &arg) == -1) { printf("error on start write, errno = %d\n", errno); exit(0); } arg = IDR_GO | IDR_CYCL; if (ioctl(filedes, IDRIO_IMM_PULSE, &arg) == -1) { printf("error on write pulse ioctl, errno = %d\n", errno); exit(0); } if (write(filedes, outarray, 0x1000) == -1) { printf("error on write #1, errno = %d\n", errno); exit(0); } if (write(filedes, (u_short *) (outarray + 0x800), 0x1002) == -1) { printf("error on write #2, errno = %d\n", errno); exit(0); } if (ioctl(filedes, IDRIO_RDY_WAIT, &arg) == -1) { printf("error on rdy wait, errno = %d\n", errno); exit(0); } if (ioctl(filedes, IDRIO_BLOCK_END, &arg) == -1) { printf("error on block end, errno = %d\n", errno); exit(0); } /* * wait for the request to send from the other end */ if (ioctl(filedes, IDRIO_ATTN_WAIT, &arg) == -1) { printf("error ATTN_WAIT, errno = %d, pass count = %d\n", errno, pass_count); exit(0); } /* * do the read in manual mode using two read calls * * issue acf2 (clear to send) to the other side of the link */ arg = 0x1000; if (ioctl(filedes, IDRIO_SET_RANGE, &arg) == -1) { printf("error on set range, errno = %d\n", errno); exit(0); } if (ioctl(filedes, IDRIO_START_READ, &arg) == -1) { printf("error on start read, errno = %d\n", errno); exit(0); } arg = IDR_GO | IDR_ACF2; if (ioctl(filedes, IDRIO_IMM_PULSE, &arg) == -1) { printf("error on write pulse ioctl, errno = %d\n", errno); exit(0); } if (read(filedes, inarray, 0x1000) == -1) { printf("error on read #1, errno = %d\n", errno); exit(0); } if (read(filedes, (u_short *) (inarray + 0x800), 0x1002) == -1) { printf("error on read #2, errno = %d\n", errno); exit(0); } if (ioctl(filedes, IDRIO_RDY_WAIT, &arg) == -1) { printf("error on rdy wait, errno = %d\n", errno); exit(0); } if (ioctl(filedes, IDRIO_BLOCK_END, &arg) == -1) { printf("error on block end, errno = %d\n", errno); exit(0); } /* * compare the two buffers */ for (j = 0; j < 0x1001; j++) if (inarray[j] != outarray[j]) { printf ("data mismatch! index = 0x%x, inarray[index] = 0x%x, outarray[index] = 0x%x\n", j, inarray[j], outarray[j]); exit(0); } } printf("master pass count = %d\n", pass_count); } }