/* * This file is part of rev-eng * Copyright (c) 2004 Gianni Tedesco * Released under the terms of the GNU GPL version 2 */ #include #include #include #include #include #include #include #include #include #include #include #if HAVE_GETOPT_H #include #endif #ifdef HAVE_GETOPT_LONG static const struct option opts[]={ {"bus", 1, 0, 'b'}, {"device", 1, 0, 'd'}, {"function", 1, 0, 'f'}, {"device-id", 1, 0, 'i'}, {"vendor-id", 1, 0, 'v'}, {"extract", 0, 0, 'x'}, {"help", 0, 0, 'h'}, {NULL, 0, 0, 0}, }; #endif #define GETOPT_OPTS "b:d:f:i:v:xh" static int opt_extract; static int intr(struct pci_dev *pci, void *priv) { printf("IRQ: %.2x:%.2x.%x vendor=0x%x device=0x%x irq=%u\n", pci->bus, pci->dev, pci->fn, pci->vendor_id, pci->device_id, pci->irq); return 1; } static int do_extract(struct pci_dev *pci, int i) { char path[128]; struct fobuf b; u_int32_t base = pci->base[i]; u_int32_t len = pci->size[i]; void *map = pci->map[i]; char *str; int ret = 1; int fd; if ( !map && !(pci->io_allowed & (1<bus, pci->dev, pci->fn, str, i); fd = open(path, O_WRONLY|O_TRUNC|O_CREAT, 0640); if ( fd < 0 ) { fprintf(stderr, "%s: open(): %s\n", path, sys_err()); return 0; } if ( map == NULL ) { u_int8_t *buf; buf = malloc(len); if ( buf != NULL ) { ret = pci_read_resource(pci, i, 0, buf, len); if ( ret == 1 ) { ret = fd_write(fd, buf, len); }else{ fprintf(stderr, "%s: pci_read_resource(): %s\n", path, sys_err2(NULL)); } free(buf); } }else{ ret = fd_write(fd, map, len); } fd_close(fd); return ret; } static void vortex_init(struct pci_dev *pci) { int idx = 0; u_int32_t ioaddr = pci->base[idx] & PCI_IO_ADDRESS; u_int32_t base = 0x80; /* EEPROM base */ u_int32_t cmd32; u_int16_t cmd16; u_int32_t eeprom[0x40]; /* EEPROM */ u_int32_t csum; u_int8_t devaddr[6]; int i, timer; printf("3COM Vortex:\n"); /* Select window 0 */ cmd16 = (1<<11) + 0; pci_write_resource(pci, idx, 0x0e, &cmd16, sizeof(cmd16)); for(i=0; i < 0x40; i++) { cmd16 = base + i; pci_write_resource(pci, idx, 10, &cmd16, sizeof(cmd16)); for(timer=10; timer >= 0; timer--) { usleep(162); pci_read_resource(pci, idx, 10, &cmd16, sizeof(cmd16)); if ( (cmd16 & 0x8000) == 0 ) break; } pci_read_resource(pci, idx, 12, &eeprom[i], sizeof(eeprom[i])); } for(i=csum=0; i < 0x18; i++) csum ^= eeprom[i]; csum = (csum ^ (csum >> 8)) & 0xff; if ( csum != 0x00 ) { while( i < 0x21) csum ^= eeprom[i++]; csum = (csum ^ (csum >> 8)) & 0xff; } if ( csum ) { printf("\tinvalid csum = %4.4x (OK for Tornado)\n", csum); } printf("\tEEPROM Station address is:"); for(i=0; i < 3; i++) ((u_int16_t *)devaddr)[i] = htons(eeprom[10 + i]); for(i=0; i < 6; i++) printf("%c%2.2x", i ? ':' : ' ', devaddr[i]); printf("\n"); /* Select window 2 */ cmd16 = (1<<11) + 2; pci_write_resource(pci, idx, 0x0e, &cmd16, sizeof(cmd16)); /* Write station address */ #if 0 for(i=0; i < 6; i++) { pci_write_resource(pci, idx, i, &devaddr[i], sizeof(devaddr[i])); } #endif if ( eeprom[13] & 0x8000 ) { printf("\tFull Duplex Capable\n"); }else{ printf("\tNot Full Duplex Capable\n"); } } static int show_device(struct pci_dev *pci, void *priv) { int i; pci_acquire_resources(pci, PCI_RES_ALL_BUT_IRQ, intr); printf("%.2x:%.2x.%x vendor=0x%x device=0x%x irq=%u %s\n", pci->bus, pci->dev, pci->fn, pci->vendor_id, pci->device_id, pci->irq, pci->name); for(i=0; i < PCI_RES_SLOTS; i++) { if ( pci->base[i] == 0 ) continue; if ( i == PCI_ROM_SLOT ) { printf("\tExpansion ROM: 0x%.8x %s [len=%u]", pci->base[i] & PCI_ROM_ADDRESS_MASK, (pci->base[i] & PCI_ROM_ADDRESS_ENABLE) ? "enabled" : "disabled", pci->size[i]); }else if ( pci->base[i] & 1 ) { printf("\tI/O slot %i: 0x%.8x [len=%u]", i, pci->base[i] & PCI_IO_ADDRESS, pci->size[i]); }else{ printf("\tMemory slot %i: 0x%.8x [len=%u]", i, pci->base[i] & PCI_MEM_ADDRESS, pci->size[i]); } if ( pci->map[i] ) printf(" [mapped to 0x%x]", pci->map[i]); if ( pci->io_allowed & (1<vendor_id == 0x10b7 && pci->device_id == 0x9200 ) vortex_init(pci); printf("\n"); return 1; } void usage(void) { } int main(int argc, char **argv) { struct pci_dev *pci; int bus, dev, fn, device, vendor; u_int32_t num; int c; if ( !pci_scan_devices() ) printf("PCI scan devices failed: %s\n", sys_err2(NULL)); device = vendor = bus = dev = fn = -1; #ifdef HAVE_GETOPT_LONG while( (c=getopt_long(argc, argv, GETOPT_OPTS, opts, NULL))!=-1 ) #else while ( (c=getopt(argc, argv, GETOPT_OPTS)) != -1 ) #endif { switch ( c ) { case 'b': if ( strnum(optarg, &num) ) return 1; bus = (int)num; break; case 'd': if ( strnum(optarg, &num) ) return 1; dev = (int)num; break; case 'f': if ( strnum(optarg, &num) ) return 1; fn = (int)num; break; case 'i': if ( strnum(optarg, &num) ) return 1; device = (int)num; break; case 'v': if ( strnum(optarg, &num) ) return 1; vendor = (int)num; break; case 'x': opt_extract = 1; break; case 'h': usage(); case '?': default: usage(); return 1; } } pci_find_devices(bus, dev, fn, device, vendor, show_device, NULL); pci_free_devices(); return 0; }