?? tor2ee.c
字號:
word a,r; int tries; int retry=0;attempt_retry: if (retry > 10) { fprintf(stderr, "Maximum retries exceeded reading position %04x\n", addr); exit(1); } /* Load the value to be written */ pci_write_long(dev, PLX_PCI_VPD_DATA, val); /* Be sure we only execute a write */ a = addr | 0x8000; pci_write_word(dev, PLX_PCI_VPD_ADDR, a); tries = 0; /* Wait for write to be validated */ for(;;) { r = pci_read_word(dev, PLX_PCI_VPD_ADDR); /* Wait a bit if it's not yet written */ if (r & 0x8000) { tries++; if (tries > 10) { retry++; goto attempt_retry; } usleep(1); } else break; } return 0;}static int read_pci_eeprom(struct pci_dev *dev, struct pci_eeprom *ee){ int x; u_int32_t v, *tmp; printf("Reading from EEPROM.."); fflush(stdout); tmp = (u_int32_t *)(ee->data); if (manual) { for (x=0;x<sizeof(ee->data)/2;x++) { ee->data[x] = plx_read_reg(x); printf("."); fflush(stdout); } } else { for (x=0;x<sizeof(ee->data)/4;x++) { v = read_eeprom_value(dev, x << 2); ee->data[x * 2] = (v & 0xFFFF0000) >> 16; ee->data[x * 2 + 1] = v & 0xFFFF; printf("."); fflush(stdout); } } printf("Done\n"); return 0;}static int write_pci_eeprom(struct pci_dev *dev, struct pci_eeprom *ee){ int x; u_int32_t v, *tmp; int writeboundary; writeboundary = ((word *)memw)[PLX_LOC_WP_BOUNDARY/2]; printf("Original Writeprotect boundary: %04x\n", writeboundary); /* Turn off write protect */ ((word *)memw)[PLX_LOC_WP_BOUNDARY/2] = 0; printf("Writing to EEPROM.."); fflush(stdout); if (manual) { /* Enable writing */ plx_write_en(); /* Write values */ for (x=sizeof(ee->data)/2-1;x>=0;x--) { plx_write_reg(x, (int)ee->data[x]); printf("."); fflush(stdout); } } else { tmp = (u_int32_t *)(ee->data); for (x=sizeof(ee->data)/4-1;x>=0;x--) { v = (ee->data[x * 2] << 16) | ee->data[x * 2 + 1]; write_eeprom_value(dev, x << 2, v); printf("."); fflush(stdout); } } printf("Done\n"); /* Restore write protect */ ((word *)memw)[PLX_LOC_WP_BOUNDARY/2] = writeboundary; return 0;}static int reset_pci_eeprom(struct pci_dev *dev){ int writeboundary; writeboundary = ((word *)memw)[PLX_LOC_WP_BOUNDARY/2]; printf("Original Writeprotect boundary: %04x\n", writeboundary); /* Turn off write protect */ ((word *)memw)[PLX_LOC_WP_BOUNDARY/2] = 0; printf("Resetting EEPROM.."); fflush(stdout); /* Enable writing */ plx_write_en(); plx_write_all(0xffff); printf("Done\n"); /* Restore write protect */ ((word *)memw)[PLX_LOC_WP_BOUNDARY/2] = writeboundary; return 0;}#if 0static void plx_reset(void){ unsigned short tmp; tmp = ((word *)memw)[0x50/2]; printf("CNTRL: %04x\n", tmp); tmp |= 0x4000; printf("Writing: %04x\n", tmp); tmp = ((word *)memw)[0x50/2]; printf("Readback: %04x\n", tmp); sleep(1); tmp = ((word *)memw)[0x50/2]; printf("CNTRL: %04x\n", tmp); tmp &= ~0x4000; ((word *)memw)[0x50/2] = tmp; tmp = ((word *)memw)[0x50/2]; printf("CNTRL: %04x\n", tmp);}#endifstatic void plx_manread(void){ int x; unsigned short reg;#if 0 read_cntrl(); printf("Cntrl is %02x\n", cntrl); cntrl &= ~0xf0ff; printf("Clearing all signals\n"); write_cntrl(); fgetc(stdin); printf("Setting CS\n"); cntrl |= BIT_EE_CS; write_cntrl(); read_cntrl(); printf("New read: %04x\n", cntrl); fgetc(stdin); printf("Setting CLK\n"); cntrl &= ~BIT_EE_CS; cntrl |= BIT_EE_CLK; write_cntrl(); fgetc(stdin); printf("Setting WR\n"); cntrl &= ~BIT_EE_CLK; cntrl |= BIT_EE_WR; write_cntrl(); fgetc(stdin); cntrl &= ~BIT_EE_WR; write_cntrl();#endif for (x=0;x<NUM_REGS;x++) { reg = plx_read_reg(x); printf("0x%02x: %04x\n", x, reg); }}static void dump_pci_eeprom(struct pci_eeprom *ee){ int x; for (x=0;x<NUM_EEREGS;x++) printf("%60s(%04x): 0x%04x\n", eeregs[x].name, eeregs[x].pos, ee->data[eeregs[x].pos/2]);}static int read_eeprom_file(char *filename, struct pci_eeprom *ee){ int res,len; int fd; len = sizeof(*ee); fd = open(filename, O_RDONLY); if (fd < 0) { fprintf(stderr, "Unable to open %s for input\n", filename); return -1; } printf("Reading from file '%s'....", filename); fflush(stdout); res = read(fd, (char *)ee, len); close(fd); if (res != len) { printf("Failed!\n"); if (res < 0) { fprintf(stderr, "Failed to read from file: %s\n", strerror(errno)); } else { fprintf(stderr, "Only read %d of %d bytes: %s\n", res, len, strerror(errno)); } return -1; } if (ee->magic != htonl(EEPROM_MAGIC)) { printf("Failed!\n"); fprintf(stderr, "File '%s' does not appear to be a Tormenta2 EEPROM file\n", filename); return -1; } if (ee->crc16 != htons(calc_crc16((char *)ee, sizeof(*ee) - 2))) { printf("Failed!\n"); fprintf(stderr, "File '%s' has improper checksum\n", filename); return -1; } printf("Done.\n"); printf("Read Revision '%s' from file '%s'\n", ee->revision, filename); return 0;}static int write_eeprom_file(char *filename, char *revision, struct pci_eeprom *ee){ int res; int len; int fd; fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0666); if (fd < 0) { fprintf(stderr, "Unable to open %s for output\n", filename); return -1; } /* Record magic */ ee->magic = htonl(EEPROM_MAGIC); /* Store revision number */ memset(ee->revision, 0, sizeof(ee->revision)); strncpy(ee->revision, revision, sizeof(ee->revision)); /* Calculate FCS on revision and data */ ee->crc16 = htons(calc_crc16((char *)ee, sizeof(*ee) - 2)); len = sizeof(*ee); printf("Writing Revision '%s' to file '%s'....", ee->revision, filename); fflush(stdout); res = write(fd, (char *)ee, len); close(fd); if (res != len) { printf("Failed!\n"); if (res < 0) { fprintf(stderr, "Failed to write to file: %s\n", strerror(errno)); } else { fprintf(stderr, "Only wrote %d of %d bytes: %s\n", res, len, strerror(errno)); } return -1; } printf("Done.\n"); return 0;}static int openmem(off_t offset, size_t len, int inport){ if (iopl(3)) { fprintf(stderr, "Unable to set I/O Permissions: %s\n", strerror(errno)); return -1; } if (memfd > -1) { fprintf(stderr, "Huh? Memory already exists?\n"); return 0; } memfd = open("/dev/mem", O_RDWR); if (memfd < 0) { fprintf(stderr, "Unable to open /dev/mem: %s\n", strerror(errno)); return -1; } memw = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, offset); if (memw == MAP_FAILED) { fprintf(stderr, "Memory map failed: %s\n", strerror(errno)); close(memfd); memfd = -1; return -1; } memlen = len; port = inport & PCI_ADDR_IO_MASK; return 0;}static char *makerev(void){ static char rev[32]; time_t t; struct tm *tm; t = time(NULL); tm = localtime(&t); strftime(rev, sizeof(rev), "Rev[%d/%m/%Y][%T]", tm); return rev;}static void closemem(void){ if (memfd > -1) { munmap(memw, memlen); close(memfd); } memfd = -1; if (pci) pci_cleanup(pci);}int detect_tormenta2(int index){ /* Detect presense of Tormenta 2 card or return -1. Sets up base addresses, etc as necessary as well. */ int which=0; char *variant; pci = pci_alloc(); pci_init(pci); pci_scan_bus(pci); dev = pci->devices; while(dev) {#if 0 printf("[%d:%d:%d] VendorID: %04x DeviceID: %04x\n", dev->bus, dev->dev, dev->func, dev->vendor_id, dev->device_id);#endif if (tor2_pci_match(dev->vendor_id, dev->device_id, &variant)) if (index == which++) break; dev = dev->next; } if (!dev) { if (which) fprintf(stderr, "Only %d Tormenta2 card(s) found\n", which); else fprintf(stderr, "No Tormenta2 card found in system\n"); return -1; } printf("Tormenta2 Card (%s) Found!\n" "Vendor ID: %04x Device ID: %04x\n" "PLX Control Base Address: 0x%08lx [0x%04lx window]\n" "PLX Control I/O Space: 0x%lx\n", variant, dev->vendor_id, dev->device_id, dev->base_addr[0], dev->size[0], dev->base_addr[1]); if (!dev->base_addr[0] || !dev->size[0]) { fprintf(stderr, "Invalid base address info\n"); return -1; } if (openmem(dev->base_addr[0], dev->size[0], dev->base_addr[1])) { fprintf(stderr, "Unable to open memory\n"); return -1; } printf("Mapped registers at %p\n", memw); return 0;}void usage(int exitstatus){ fprintf(stderr, "tor2ee -- Tormenta 2 EEPROM controller\n""Usage: tor2ee command [args...]\n"" tor2ee detect\n"" -- Detect presense of Tormenta 2 card\n"" tor2ee [man]save <filename> [revision]\n"" -- Read contents of eeprom and write to file\n"" tor2ee reset\n"" -- Reset the PLX EEPROM\n"" tor2ee manread\n"" -- Manually read registers\n"" tor2ee [man]load <filename>\n"" -- Write EEPROM from contents of file\n"" tor2ee modify <filename> [hex offset] [hex value]\n"" -- Change a specific offset and value in a given filename\n"" tor2ee verify <filename>\n"" -- Verify integrity of EEPROM file\n"" tor2ee compare <filename>\n"" -- Compare EEPROM file to current contents\n"" tor2ee dump [filename]\n"" -- Dump current EEPROM contents or filename if specified\n"); exit(exitstatus);}#define MODE_DETECT 0#define MODE_DUMP 1#define MODE_SAVE 2#define MODE_MODIFY 3#define MODE_LOAD 4#define MODE_RESET 5#define MODE_MANREAD 6static void modify(struct pci_eeprom *ee, int reg, int val){ int x; char *regn = "<Unknown>"; for (x=0;x<NUM_EEREGS;x++) if (eeregs[x].pos == reg) regn = eeregs[x].name; ee->data[reg/2] = val; printf("Setting %s to %04x\n", regn, val);}int main(int argc, char *argv[]){ struct pci_eeprom ee; int mode; int reg; int val; char tmp[32]; char *readfile = NULL; char *writefile = NULL; char *revision = NULL; if (argc < 2) { usage(1); } if (!strcasecmp(argv[1], "dump")) { mode = MODE_DUMP; if (argc > 2) readfile = argv[2]; } else if (!strcasecmp(argv[1], "save") || !strcasecmp(argv[1], "mansave")) { if (argc < 3) usage(1); writefile = argv[2]; if (argc > 3) revision = argv[3]; else revision = makerev(); mode = MODE_SAVE; if (!strcasecmp(argv[1], "mansave")) manual = 1; } else if (!strcasecmp(argv[1], "detect")) { mode = MODE_DETECT; } else if (!strcasecmp(argv[1], "load") || !strcasecmp(argv[1], "manload")) { if (argc < 3) usage(1); readfile = argv[2]; if (!strcasecmp(argv[1], "manload")) manual = 1; mode = MODE_LOAD; } else if (!strcasecmp(argv[1], "reset")) { mode = MODE_RESET; } else if (!strcasecmp(argv[1], "manread")) { mode = MODE_MANREAD; } else if (!strcasecmp(argv[1], "modify")) { if (argc < 5) usage(1); readfile = writefile = argv[2]; if ((sscanf(argv[3], "%x", ®) != 1) || (reg >= (NUM_REGS) * 2) || (reg < 0)) { fprintf(stderr, "Invalid register number: %s\n", argv[3]); usage(1); } if (sscanf(argv[4], "%x", &val) != 1) { fprintf(stderr, "Invalid value number: %s\n", argv[3]); usage(1); } mode = MODE_MODIFY; } else { usage(1); } if (detect_tormenta2(0)) { fprintf(stderr, "Tormenta 2 Not found in System\n"); closemem(); exit(1); } if (mode == MODE_RESET) { reset_pci_eeprom(dev); } if (mode == MODE_MANREAD) { plx_manread(); } if ((mode == MODE_DUMP)) { if (readfile) { if (read_eeprom_file(readfile, &ee)) { fprintf(stderr, "Unable to read EEPROM file\n"); closemem(); exit(1); } } else { if (read_pci_eeprom(dev, &ee)) { fprintf(stderr, "Unable to read existing EEPROM\n"); closemem(); exit(1); } } dump_pci_eeprom(&ee); } if (mode == MODE_SAVE) { if (read_pci_eeprom(dev, &ee)) { fprintf(stderr, "Unable to read existiing EEPROM\n"); closemem(); exit(1); } if (write_eeprom_file(writefile, revision, &ee)) { fprintf(stderr, "Unable to save EEPROM contents\n"); closemem(); exit(1); } } if (mode == MODE_MODIFY) { if (read_eeprom_file(readfile, &ee)) { fprintf(stderr, "Unable to read EEPROM file\n"); closemem(); exit(1); } modify(&ee, reg, val); strncpy(tmp, ee.revision, sizeof(tmp)); if (write_eeprom_file(writefile, tmp, &ee)) { fprintf(stderr, "Unable to write EEPROM file\n"); closemem(); exit(1); } } if (mode == MODE_LOAD) { if (read_eeprom_file(readfile, &ee)) { fprintf(stderr, "Unable to read EEPROM file\n"); closemem(); exit(1); } if (write_pci_eeprom(dev, &ee)) { fprintf(stderr, "Unable to write to EEPROM\n"); closemem(); exit(1); } printf("EEPROM successfully written. Please reboot to make changes\n"); printf("take effect.\n"); } closemem(); return 0;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -