/* * setest.c * * Purpose * Test the serial port. * * Description * An external loopback dongle is required to use this program. * Twiddling the serial port also requires executiion by root. * * History * Jul 26, 1999 - Andrew E. Mileski * General cleanup and commit to CVS. * * Jul 2, 1999 - Woody Suwalski * Concevied, coded, and tested. */ #include #include #include #include #include #include #include #include /* these globals handle the differences between Linux 2.0.x and 2.2.x */ #define IO_BASE_20 0xE0000000 #define IO_BASE_22 0x7C000000 #define PAGE_SIZE 0x1000 static long io_base = IO_BASE_22; static char* pIO; #define outb(p, v) *(pIO+(p)) = (char)v #define inb(p) *(pIO+(p)) /* Signal bits */ #define DTR 0x01 #define RTS 0x02 #define CTS 0x10 #define DSR 0x20 #define RI 0x40 #define DCD 0x80 /* Flags */ #define DATA_READY 0x01 /* Register addresses */ #define UARTBASE 0x3f8 #define XMITREG (UARTBASE + 0) #define RECVREG (UARTBASE + 0) #define CTRLREG (UARTBASE + 4) #define UARTREG (UARTBASE + 5) #define STATREG (UARTBASE + 6) static int devmem = 0; void dump_regs(int debugflag) { int i; if (!debugflag) return; printf("UART: "); for(i = 0; i < 8; i++) printf("0x%02x ", inb(UARTBASE + i)); printf("\n"); } int main(int argc, char *argv[]) { volatile unsigned char ctemp; int i; int debugflag = 0; char textline[256]; fprintf(stderr, "Serial Port Test Tool V.1.0, REBEL.COM 1999\n"); if (getuid()) { fprintf (stderr, "This program must be run as root!\n"); return 1; } devmem = open ("/dev/mem", O_RDWR); if (devmem < 0) { perror("Could not open /dev/mem"); return 1; } i=open("/proc/version",O_RDONLY); if (i==-1) { printf("\n/proc directory is not mounted; assuming Linux 2.2.x"); } else { read(i,textline,255); close(i); if (strstr(textline,"2.0.")) { printf("Using Linux 2.0 memory map\n"); io_base = IO_BASE_20; } } pIO = mmap(0,PAGE_SIZE,PROT_READ|PROT_WRITE,MAP_FILE|MAP_SHARED,devmem,io_base); if (pIO == NULL) printf ("Memory access error!\n"); dump_regs(debugflag); /* Read the UART queue (16 bytes) to flush any potential garbage */ outb(CTRLREG, 0); usleep(100); outb(XMITREG, 0x96); usleep(100); ctemp = inb(UARTREG); ctemp = inb(UARTREG); for (i = 1; i <= 32 && (ctemp & DATA_READY); i++) { usleep(100); ctemp = inb(RECVREG); usleep(100); ctemp = inb(UARTREG); } /* UART is bad if we have to read more than 16 times */ if (i > 17) { fprintf(stderr, "Error: UART constantly generating data!\n"); dump_regs(1); return 1; } /* Now UART is empty, so send 1 char and see if it is received */ outb (XMITREG, 0xA5); usleep(100); ctemp = inb(UARTREG); if (!ctemp & DATA_READY) { fprintf(stderr, "Error: Serial port not receiving data!\n"); dump_regs(1); return 2; } usleep(100); ctemp = inb(RECVREG); if (ctemp != 0xA5) { fprintf(stderr, "Error: Serial port receiving bad data!(0xA5 != 0x%02X)\n",ctemp); dump_regs(1); return 3; } /* Repeat with a different char */ usleep(100); outb (XMITREG, 0x5A); usleep(100); ctemp = inb(UARTREG); if (!ctemp & DATA_READY) { fprintf(stderr, "Error: Serial port not receiving data(2)!\n"); dump_regs(1); return 2; } usleep(100); ctemp = inb(RECVREG); if (ctemp != 0x5A) { fprintf(stderr, "Error: Serial port receiving bad data (2)! (0x5A != 0x%02X)\n",ctemp); dump_regs(1); return 3; } dump_regs(debugflag); /* clear DTR and RTS bits */ outb (CTRLREG, 0); usleep(100); ctemp = inb(STATREG); if ((ctemp & CTS) || (ctemp & DSR) || (ctemp & RI) || (ctemp & DCD)) { fprintf(stderr, "Error: Serial port control lines problem!\n"); dump_regs(1); exit(4); } dump_regs(debugflag); outb (CTRLREG, DTR); usleep(100); ctemp = inb(STATREG); if (!(ctemp & CTS) || !(ctemp & DSR) || (ctemp & RI) || (ctemp & DCD)) { fprintf(stderr, "Error: Serial port DTR control line problem!\n"); dump_regs(1); return 5; } dump_regs(debugflag); outb (CTRLREG, RTS); usleep(100); dump_regs(debugflag); ctemp = inb(STATREG); if ((ctemp & CTS) || (ctemp & DSR) || !(ctemp & RI) || !(ctemp & DCD)) { fprintf(stderr, "Error: Serial port RTS control line problem!\n"); dump_regs(1); return 6; } dump_regs(debugflag); fprintf(stderr, "All tests were successful\n"); munmap(pIO,PAGE_SIZE); close (devmem); return 0; }