Annotation of embedaddon/pciutils/setpci.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  *     The PCI Utilities -- Manipulate PCI Configuration Registers
                      3:  *
                      4:  *     Copyright (c) 1998--2008 Martin Mares <mj@ucw.cz>
                      5:  *
                      6:  *     Can be freely distributed and used under the terms of the GNU GPL.
                      7:  */
                      8: 
                      9: #include <stdio.h>
                     10: #include <string.h>
                     11: #include <stdlib.h>
                     12: #include <stdarg.h>
                     13: #include <errno.h>
                     14: 
                     15: #define PCIUTILS_SETPCI
                     16: #include "pciutils.h"
                     17: 
                     18: static int force;                      /* Don't complain if no devices match */
                     19: static int verbose;                    /* Verbosity level */
                     20: static int demo_mode;                  /* Only show */
                     21: 
                     22: const char program_name[] = "setpci";
                     23: 
                     24: static struct pci_access *pacc;
                     25: 
                     26: struct value {
                     27:   unsigned int value;
                     28:   unsigned int mask;
                     29: };
                     30: 
                     31: struct op {
                     32:   struct op *next;
                     33:   struct pci_dev **dev_vector;
                     34:   u16 cap_type;                                /* PCI_CAP_xxx or 0 */
                     35:   u16 cap_id;
                     36:   unsigned int addr;
                     37:   unsigned int width;                  /* Byte width of the access */
                     38:   unsigned int num_values;             /* Number of values to write; 0=read */
                     39:   struct value values[0];
                     40: };
                     41: 
                     42: static struct op *first_op, **last_op = &first_op;
                     43: static unsigned int max_values[] = { 0, 0xff, 0xffff, 0, 0xffffffff };
                     44: 
                     45: static struct pci_dev **
                     46: select_devices(struct pci_filter *filt)
                     47: {
                     48:   struct pci_dev *z, **a, **b;
                     49:   int cnt = 1;
                     50: 
                     51:   for (z=pacc->devices; z; z=z->next)
                     52:     if (pci_filter_match(filt, z))
                     53:       cnt++;
                     54:   a = b = xmalloc(sizeof(struct device *) * cnt);
                     55:   for (z=pacc->devices; z; z=z->next)
                     56:     if (pci_filter_match(filt, z))
                     57:       *a++ = z;
                     58:   *a = NULL;
                     59:   return b;
                     60: }
                     61: 
                     62: static void PCI_PRINTF(1,2)
                     63: trace(const char *fmt, ...)
                     64: {
                     65:   va_list args;
                     66:   va_start(args, fmt);
                     67:   if (verbose)
                     68:     vprintf(fmt, args);
                     69:   va_end(args);
                     70: }
                     71: 
                     72: static void
                     73: exec_op(struct op *op, struct pci_dev *dev)
                     74: {
                     75:   const char * const formats[] = { NULL, " %02x", " %04x", NULL, " %08x" };
                     76:   const char * const mask_formats[] = { NULL, " %02x->(%02x:%02x)->%02x", " %04x->(%04x:%04x)->%04x", NULL, " %08x->(%08x:%08x)->%08x" };
                     77:   unsigned int i, x, y;
                     78:   int addr = 0;
                     79:   int width = op->width;
                     80:   char slot[16];
                     81: 
                     82:   sprintf(slot, "%04x:%02x:%02x.%x", dev->domain, dev->bus, dev->dev, dev->func);
                     83:   trace("%s ", slot);
                     84:   if (op->cap_type)
                     85:     {
                     86:       struct pci_cap *cap;
                     87:       cap = pci_find_cap(dev, op->cap_id, op->cap_type);
                     88:       if (cap)
                     89:        addr = cap->addr;
                     90:       else
                     91:        die("%s: %s %04x not found", slot, ((op->cap_type == PCI_CAP_NORMAL) ? "Capability" : "Extended capability"), op->cap_id);
                     92:       trace(((op->cap_type == PCI_CAP_NORMAL) ? "(cap %02x @%02x) " : "(ecap %04x @%03x) "), op->cap_id, addr);
                     93:     }
                     94:   addr += op->addr;
                     95:   trace("@%02x", addr);
                     96: 
                     97:   /* We have already checked it when parsing, but addressing relative to capabilities can change the address. */
                     98:   if (addr & (width-1))
                     99:     die("%s: Unaligned access of width %d to register %04x", slot, width, addr);
                    100:   if (addr + width > 0x1000)
                    101:     die("%s: Access of width %d to register %04x out of range", slot, width, addr);
                    102: 
                    103:   if (op->num_values)
                    104:     {
                    105:       for (i=0; i<op->num_values; i++)
                    106:        {
                    107:          if ((op->values[i].mask & max_values[width]) == max_values[width])
                    108:            {
                    109:              x = op->values[i].value;
                    110:              trace(formats[width], op->values[i].value);
                    111:            }
                    112:          else
                    113:            {
                    114:              switch (width)
                    115:                {
                    116:                case 1:
                    117:                  y = pci_read_byte(dev, addr);
                    118:                  break;
                    119:                case 2:
                    120:                  y = pci_read_word(dev, addr);
                    121:                  break;
                    122:                default:
                    123:                  y = pci_read_long(dev, addr);
                    124:                  break;
                    125:                }
                    126:              x = (y & ~op->values[i].mask) | op->values[i].value;
                    127:              trace(mask_formats[width], y, op->values[i].value, op->values[i].mask, x);
                    128:            }
                    129:          if (!demo_mode)
                    130:            {
                    131:              switch (width)
                    132:                {
                    133:                case 1:
                    134:                  pci_write_byte(dev, addr, x);
                    135:                  break;
                    136:                case 2:
                    137:                  pci_write_word(dev, addr, x);
                    138:                  break;
                    139:                default:
                    140:                  pci_write_long(dev, addr, x);
                    141:                  break;
                    142:                }
                    143:            }
                    144:          addr += width;
                    145:        }
                    146:       trace("\n");
                    147:     }
                    148:   else
                    149:     {
                    150:       trace(" = ");
                    151:       switch (width)
                    152:        {
                    153:        case 1:
                    154:          x = pci_read_byte(dev, addr);
                    155:          break;
                    156:        case 2:
                    157:          x = pci_read_word(dev, addr);
                    158:          break;
                    159:        default:
                    160:          x = pci_read_long(dev, addr);
                    161:          break;
                    162:        }
                    163:       printf(formats[width]+1, x);
                    164:       putchar('\n');
                    165:     }
                    166: }
                    167: 
                    168: static void
                    169: execute(struct op *op)
                    170: {
                    171:   struct pci_dev **vec = NULL;
                    172:   struct pci_dev **pdev, *dev;
                    173:   struct op *oops;
                    174: 
                    175:   while (op)
                    176:     {
                    177:       pdev = vec = op->dev_vector;
                    178:       while (dev = *pdev++)
                    179:        for (oops=op; oops && oops->dev_vector == vec; oops=oops->next)
                    180:          exec_op(oops, dev);
                    181:       while (op && op->dev_vector == vec)
                    182:        op = op->next;
                    183:     }
                    184: }
                    185: 
                    186: static void
                    187: scan_ops(struct op *op)
                    188: {
                    189:   if (demo_mode)
                    190:     return;
                    191:   while (op)
                    192:     {
                    193:       if (op->num_values)
                    194:        pacc->writeable = 1;
                    195:       op = op->next;
                    196:     }
                    197: }
                    198: 
                    199: struct reg_name {
                    200:   unsigned int cap;
                    201:   unsigned int offset;
                    202:   unsigned int width;
                    203:   const char *name;
                    204: };
                    205: 
                    206: static const struct reg_name pci_reg_names[] = {
                    207:   {       0, 0x00, 2, "VENDOR_ID" },
                    208:   {       0, 0x02, 2, "DEVICE_ID" },
                    209:   {       0, 0x04, 2, "COMMAND" },
                    210:   {       0, 0x06, 2, "STATUS" },
                    211:   {       0, 0x08, 1, "REVISION" },
                    212:   {       0, 0x09, 1, "CLASS_PROG" },
                    213:   {       0, 0x0a, 2, "CLASS_DEVICE" },
                    214:   {       0, 0x0c, 1, "CACHE_LINE_SIZE" },
                    215:   {       0, 0x0d, 1, "LATENCY_TIMER" },
                    216:   {       0, 0x0e, 1, "HEADER_TYPE" },
                    217:   {       0, 0x0f, 1, "BIST" },
                    218:   {       0, 0x10, 4, "BASE_ADDRESS_0" },
                    219:   {       0, 0x14, 4, "BASE_ADDRESS_1" },
                    220:   {       0, 0x18, 4, "BASE_ADDRESS_2" },
                    221:   {       0, 0x1c, 4, "BASE_ADDRESS_3" },
                    222:   {       0, 0x20, 4, "BASE_ADDRESS_4" },
                    223:   {       0, 0x24, 4, "BASE_ADDRESS_5" },
                    224:   {       0, 0x28, 4, "CARDBUS_CIS" },
                    225:   {       0, 0x2c, 4, "SUBSYSTEM_VENDOR_ID" },
                    226:   {       0, 0x2e, 2, "SUBSYSTEM_ID" },
                    227:   {       0, 0x30, 4, "ROM_ADDRESS" },
                    228:   {       0, 0x3c, 1, "INTERRUPT_LINE" },
                    229:   {       0, 0x3d, 1, "INTERRUPT_PIN" },
                    230:   {       0, 0x3e, 1, "MIN_GNT" },
                    231:   {       0, 0x3f, 1, "MAX_LAT" },
                    232:   {       0, 0x18, 1, "PRIMARY_BUS" },
                    233:   {       0, 0x19, 1, "SECONDARY_BUS" },
                    234:   {       0, 0x1a, 1, "SUBORDINATE_BUS" },
                    235:   {       0, 0x1b, 1, "SEC_LATENCY_TIMER" },
                    236:   {       0, 0x1c, 1, "IO_BASE" },
                    237:   {       0, 0x1d, 1, "IO_LIMIT" },
                    238:   {       0, 0x1e, 2, "SEC_STATUS" },
                    239:   {       0, 0x20, 2, "MEMORY_BASE" },
                    240:   {       0, 0x22, 2, "MEMORY_LIMIT" },
                    241:   {       0, 0x24, 2, "PREF_MEMORY_BASE" },
                    242:   {       0, 0x26, 2, "PREF_MEMORY_LIMIT" },
                    243:   {       0, 0x28, 4, "PREF_BASE_UPPER32" },
                    244:   {       0, 0x2c, 4, "PREF_LIMIT_UPPER32" },
                    245:   {       0, 0x30, 2, "IO_BASE_UPPER16" },
                    246:   {       0, 0x32, 2, "IO_LIMIT_UPPER16" },
                    247:   {       0, 0x38, 4, "BRIDGE_ROM_ADDRESS" },
                    248:   {       0, 0x3e, 2, "BRIDGE_CONTROL" },
                    249:   {       0, 0x10, 4, "CB_CARDBUS_BASE" },
                    250:   {       0, 0x14, 2, "CB_CAPABILITIES" },
                    251:   {       0, 0x16, 2, "CB_SEC_STATUS" },
                    252:   {       0, 0x18, 1, "CB_BUS_NUMBER" },
                    253:   {       0, 0x19, 1, "CB_CARDBUS_NUMBER" },
                    254:   {       0, 0x1a, 1, "CB_SUBORDINATE_BUS" },
                    255:   {       0, 0x1b, 1, "CB_CARDBUS_LATENCY" },
                    256:   {       0, 0x1c, 4, "CB_MEMORY_BASE_0" },
                    257:   {       0, 0x20, 4, "CB_MEMORY_LIMIT_0" },
                    258:   {       0, 0x24, 4, "CB_MEMORY_BASE_1" },
                    259:   {       0, 0x28, 4, "CB_MEMORY_LIMIT_1" },
                    260:   {       0, 0x2c, 2, "CB_IO_BASE_0" },
                    261:   {       0, 0x2e, 2, "CB_IO_BASE_0_HI" },
                    262:   {       0, 0x30, 2, "CB_IO_LIMIT_0" },
                    263:   {       0, 0x32, 2, "CB_IO_LIMIT_0_HI" },
                    264:   {       0, 0x34, 2, "CB_IO_BASE_1" },
                    265:   {       0, 0x36, 2, "CB_IO_BASE_1_HI" },
                    266:   {       0, 0x38, 2, "CB_IO_LIMIT_1" },
                    267:   {       0, 0x3a, 2, "CB_IO_LIMIT_1_HI" },
                    268:   {       0, 0x40, 2, "CB_SUBSYSTEM_VENDOR_ID" },
                    269:   {       0, 0x42, 2, "CB_SUBSYSTEM_ID" },
                    270:   {       0, 0x44, 4, "CB_LEGACY_MODE_BASE" },
                    271:   { 0x10001,    0, 0, "CAP_PM" },
                    272:   { 0x10002,    0, 0, "CAP_AGP" },
                    273:   { 0x10003,    0, 0, "CAP_VPD" },
                    274:   { 0x10004,    0, 0, "CAP_SLOTID" },
                    275:   { 0x10005,    0, 0, "CAP_MSI" },
                    276:   { 0x10006,    0, 0, "CAP_CHSWP" },
                    277:   { 0x10007,    0, 0, "CAP_PCIX" },
                    278:   { 0x10008,    0, 0, "CAP_HT" },
                    279:   { 0x10009,    0, 0, "CAP_VNDR" },
                    280:   { 0x1000a,    0, 0, "CAP_DBG" },
                    281:   { 0x1000b,    0, 0, "CAP_CCRC" },
                    282:   { 0x1000c,    0, 0, "CAP_HOTPLUG" },
                    283:   { 0x1000d,    0, 0, "CAP_SSVID" },
                    284:   { 0x1000e,    0, 0, "CAP_AGP3" },
                    285:   { 0x1000f,    0, 0, "CAP_SECURE" },
                    286:   { 0x10010,    0, 0, "CAP_EXP" },
                    287:   { 0x10011,    0, 0, "CAP_MSIX" },
                    288:   { 0x10012,    0, 0, "CAP_SATA" },
                    289:   { 0x10013,    0, 0, "CAP_AF" },
                    290:   { 0x20001,   0, 0, "ECAP_AER" },
                    291:   { 0x20002,   0, 0, "ECAP_VC" },
                    292:   { 0x20003,   0, 0, "ECAP_DSN" },
                    293:   { 0x20004,   0, 0, "ECAP_PB" },
                    294:   { 0x20005,   0, 0, "ECAP_RCLINK" },
                    295:   { 0x20006,   0, 0, "ECAP_RCILINK" },
                    296:   { 0x20007,   0, 0, "ECAP_RCECOLL" },
                    297:   { 0x20008,   0, 0, "ECAP_MFVC" },
                    298:   { 0x2000a,   0, 0, "ECAP_RBCB" },
                    299:   { 0x2000b,   0, 0, "ECAP_VNDR" },
                    300:   { 0x2000d,   0, 0, "ECAP_ACS" },
                    301:   { 0x2000e,   0, 0, "ECAP_ARI" },
                    302:   { 0x2000f,   0, 0, "ECAP_ATS" },
                    303:   { 0x20010,   0, 0, "ECAP_SRIOV" },
                    304:   {       0,    0, 0, NULL }
                    305: };
                    306: 
                    307: static void
                    308: dump_registers(void)
                    309: {
                    310:   const struct reg_name *r;
                    311: 
                    312:   printf("cap pos w name\n");
                    313:   for (r = pci_reg_names; r->name; r++)
                    314:     {
                    315:       if (r->cap >= 0x20000)
                    316:        printf("%04x", r->cap - 0x20000);
                    317:       else if (r->cap)
                    318:        printf("  %02x", r->cap - 0x10000);
                    319:       else
                    320:        printf("    ");
                    321:       printf(" %02x %c %s\n", r->offset, "-BW?L"[r->width], r->name);
                    322:     }
                    323: }
                    324: 
                    325: static void NONRET
                    326: usage(void)
                    327: {
                    328:   fprintf(stderr,
                    329: "Usage: setpci [<options>] (<device>+ <reg>[=<values>]*)*\n"
                    330: "\n"
                    331: "General options:\n"
                    332: "-f\t\tDon't complain if there's nothing to do\n"
                    333: "-v\t\tBe verbose\n"
                    334: "-D\t\tList changes, don't commit them\n"
                    335: "--dumpregs\tDump all known register names and exit\n"
                    336: "\n"
                    337: "PCI access options:\n"
                    338: GENERIC_HELP
                    339: "\n"
                    340: "Setting commands:\n"
                    341: "<device>:\t-s [[[<domain>]:][<bus>]:][<slot>][.[<func>]]\n"
                    342: "\t\t-d [<vendor>]:[<device>]\n"
                    343: "<reg>:\t\t<base>[+<offset>][.(B|W|L)]\n"
                    344: "<base>:\t\t<address>\n"
                    345: "\t\t<named-register>\n"
                    346: "\t\t[E]CAP_<capability-name>\n"
                    347: "\t\t[E]CAP<capability-number>\n"
                    348: "<values>:\t<value>[,<value>...]\n"
                    349: "<value>:\t<hex>\n"
                    350: "\t\t<hex>:<mask>\n");
                    351:   exit(0);
                    352: }
                    353: 
                    354: static void NONRET PCI_PRINTF(1,2)
                    355: parse_err(const char *msg, ...)
                    356: {
                    357:   va_list args;
                    358:   va_start(args, msg);
                    359:   fprintf(stderr, "setpci: ");
                    360:   vfprintf(stderr, msg, args);
                    361:   fprintf(stderr, ".\nTry `setpci --help' for more information.\n");
                    362:   exit(1);
                    363: }
                    364: 
                    365: static int
                    366: parse_options(int argc, char **argv)
                    367: {
                    368:   const char opts[] = GENERIC_OPTIONS;
                    369:   int i=1;
                    370: 
                    371:   if (argc == 2)
                    372:     {
                    373:       if (!strcmp(argv[1], "--help"))
                    374:        usage();
                    375:       if (!strcmp(argv[1], "--version"))
                    376:        {
                    377:          puts("setpci version " PCIUTILS_VERSION);
                    378:          exit(0);
                    379:        }
                    380:       if (!strcmp(argv[1], "--dumpregs"))
                    381:        {
                    382:          dump_registers();
                    383:          exit(0);
                    384:        }
                    385:     }
                    386: 
                    387:   while (i < argc && argv[i][0] == '-')
                    388:     {
                    389:       char *c = argv[i++] + 1;
                    390:       char *d = c;
                    391:       char *e;
                    392:       while (*c)
                    393:        switch (*c)
                    394:          {
                    395:          case 0:
                    396:            break;
                    397:          case 'v':
                    398:            verbose++;
                    399:            c++;
                    400:            break;
                    401:          case 'f':
                    402:            force++;
                    403:            c++;
                    404:            break;
                    405:          case 'D':
                    406:            demo_mode++;
                    407:            c++;
                    408:            break;
                    409:          default:
                    410:            if (e = strchr(opts, *c))
                    411:              {
                    412:                char *arg;
                    413:                c++;
                    414:                if (e[1] == ':')
                    415:                  {
                    416:                    if (*c)
                    417:                      arg = c;
                    418:                    else if (i < argc)
                    419:                      arg = argv[i++];
                    420:                    else
                    421:                      parse_err("Option -%c requires an argument", *e);
                    422:                    c = "";
                    423:                  }
                    424:                else
                    425:                  arg = NULL;
                    426:                if (!parse_generic_option(*e, pacc, arg))
                    427:                  parse_err("Unable to parse option -%c", *e);
                    428:              }
                    429:            else
                    430:              {
                    431:                if (c != d)
                    432:                  parse_err("Invalid or misplaced option -%c", *c);
                    433:                return i-1;
                    434:              }
                    435:          }
                    436:     }
                    437: 
                    438:   return i;
                    439: }
                    440: 
                    441: static int parse_filter(int argc, char **argv, int i, struct pci_filter *filter)
                    442: {
                    443:   char *c = argv[i++];
                    444:   char *d;
                    445: 
                    446:   if (!c[1] || !strchr("sd", c[1]))
                    447:     parse_err("Invalid option -%c", c[1]);
                    448:   if (c[2])
                    449:     d = (c[2] == '=') ? c+3 : c+2;
                    450:   else if (i < argc)
                    451:     d = argv[i++];
                    452:   else
                    453:     parse_err("Option -%c requires an argument", c[1]);
                    454:   switch (c[1])
                    455:     {
                    456:     case 's':
                    457:       if (d = pci_filter_parse_slot(filter, d))
                    458:        parse_err("Unable to parse filter -s %s", d);
                    459:       break;
                    460:     case 'd':
                    461:       if (d = pci_filter_parse_id(filter, d))
                    462:        parse_err("Unable to parse filter -d %s", d);
                    463:       break;
                    464:     default:
                    465:       parse_err("Unknown filter option -%c", c[1]);
                    466:     }
                    467: 
                    468:   return i;
                    469: }
                    470: 
                    471: static const struct reg_name *parse_reg_name(char *name)
                    472: {
                    473:   const struct reg_name *r;
                    474: 
                    475:   for (r = pci_reg_names; r->name; r++)
                    476:     if (!strcasecmp(r->name, name))
                    477:       return r;
                    478:   return NULL;
                    479: }
                    480: 
                    481: static int parse_x32(char *c, char **stopp, unsigned int *resp)
                    482: {
                    483:   char *stop;
                    484:   unsigned long int l;
                    485: 
                    486:   if (!*c)
                    487:     return -1;
                    488:   errno = 0;
                    489:   l = strtoul(c, &stop, 16);
                    490:   if (errno)
                    491:     return -1;
                    492:   if ((l & ~0U) != l)
                    493:     return -1;
                    494:   *resp = l;
                    495:   if (*stop)
                    496:     {
                    497:       if (stopp)
                    498:        *stopp = stop;
                    499:       return 0;
                    500:     }
                    501:   else
                    502:     {
                    503:       if (stopp)
                    504:        *stopp = NULL;
                    505:       return 1;
                    506:     }
                    507: }
                    508: 
                    509: static void parse_register(struct op *op, char *base)
                    510: {
                    511:   const struct reg_name *r;
                    512:   unsigned int cap;
                    513: 
                    514:   op->cap_type = op->cap_id = 0;
                    515:   if (parse_x32(base, NULL, &op->addr) > 0)
                    516:     return;
                    517:   else if (r = parse_reg_name(base))
                    518:     {
                    519:       switch (r->cap & 0xff0000)
                    520:        {
                    521:        case 0x10000:
                    522:          op->cap_type = PCI_CAP_NORMAL;
                    523:          break;
                    524:        case 0x20000:
                    525:          op->cap_type = PCI_CAP_EXTENDED;
                    526:          break;
                    527:        }
                    528:       op->cap_id = r->cap & 0xffff;
                    529:       op->addr = r->offset;
                    530:       if (r->width && !op->width)
                    531:        op->width = r->width;
                    532:       return;
                    533:     }
                    534:   else if (!strncasecmp(base, "CAP", 3))
                    535:     {
                    536:       if (parse_x32(base+3, NULL, &cap) > 0 && cap < 0x100)
                    537:        {
                    538:          op->cap_type = PCI_CAP_NORMAL;
                    539:          op->cap_id = cap;
                    540:          op->addr = 0;
                    541:          return;
                    542:        }
                    543:     }
                    544:   else if (!strncasecmp(base, "ECAP", 4))
                    545:     {
                    546:       if (parse_x32(base+4, NULL, &cap) > 0 && cap < 0x1000)
                    547:        {
                    548:          op->cap_type = PCI_CAP_EXTENDED;
                    549:          op->cap_id = cap;
                    550:          op->addr = 0;
                    551:          return;
                    552:        }
                    553:     }
                    554:   parse_err("Unknown register \"%s\"", base);
                    555: }
                    556: 
                    557: static void parse_op(char *c, struct pci_dev **selected_devices)
                    558: {
                    559:   char *base, *offset, *width, *value;
                    560:   char *e, *f;
                    561:   int n, j;
                    562:   struct op *op;
                    563: 
                    564:   /* Split the argument */
                    565:   base = xstrdup(c);
                    566:   if (value = strchr(base, '='))
                    567:     *value++ = 0;
                    568:   if (width = strchr(base, '.'))
                    569:     *width++ = 0;
                    570:   if (offset = strchr(base, '+'))
                    571:     *offset++ = 0;
                    572: 
                    573:   /* Look for setting of values and count how many */
                    574:   n = 0;
                    575:   if (value)
                    576:     {
                    577:       if (!*value)
                    578:        parse_err("Missing value");
                    579:       n++;
                    580:       for (e=value; *e; e++)
                    581:        if (*e == ',')
                    582:          n++;
                    583:     }
                    584: 
                    585:   /* Allocate the operation */
                    586:   op = xmalloc(sizeof(struct op) + n*sizeof(struct value));
                    587:   op->dev_vector = selected_devices;
                    588:   op->num_values = n;
                    589: 
                    590:   /* What is the width suffix? */
                    591:   if (width)
                    592:     {
                    593:       if (width[1])
                    594:        parse_err("Invalid width \"%s\"", width);
                    595:       switch (*width & 0xdf)
                    596:        {
                    597:        case 'B':
                    598:          op->width = 1; break;
                    599:        case 'W':
                    600:          op->width = 2; break;
                    601:        case 'L':
                    602:          op->width = 4; break;
                    603:        default:
                    604:          parse_err("Invalid width \"%c\"", *width);
                    605:        }
                    606:     }
                    607:   else
                    608:     op->width = 0;
                    609: 
                    610:   /* Find the register */
                    611:   parse_register(op, base);
                    612:   if (!op->width)
                    613:     parse_err("Missing width");
                    614: 
                    615:   /* Add offset */
                    616:   if (offset)
                    617:     {
                    618:       unsigned int off;
                    619:       if (parse_x32(offset, NULL, &off) <= 0 || off >= 0x1000)
                    620:        parse_err("Invalid offset \"%s\"", offset);
                    621:       op->addr += off;
                    622:     }
                    623: 
                    624:   /* Check range */
                    625:   if (op->addr >= 0x1000 || op->addr + op->width*(n ? n : 1) > 0x1000)
                    626:     parse_err("Register number %02x out of range", op->addr);
                    627:   if (op->addr & (op->width - 1))
                    628:     parse_err("Unaligned register address %02x", op->addr);
                    629: 
                    630:   /* Parse the values */
                    631:   for (j=0; j<n; j++)
                    632:     {
                    633:       unsigned int ll, lim;
                    634:       e = strchr(value, ',');
                    635:       if (e)
                    636:        *e++ = 0;
                    637:       if (parse_x32(value, &f, &ll) < 0 || f && *f != ':')
                    638:        parse_err("Invalid value \"%s\"", value);
                    639:       lim = max_values[op->width];
                    640:       if (ll > lim && ll < ~0UL - lim)
                    641:        parse_err("Value \"%s\" is out of range", value);
                    642:       op->values[j].value = ll;
                    643:       if (f && *f == ':')
                    644:        {
                    645:          if (parse_x32(f+1, NULL, &ll) <= 0)
                    646:            parse_err("Invalid mask \"%s\"", f+1);
                    647:          if (ll > lim && ll < ~0UL - lim)
                    648:            parse_err("Mask \"%s\" is out of range", f+1);
                    649:          op->values[j].mask = ll;
                    650:          op->values[j].value &= ll;
                    651:        }
                    652:       else
                    653:        op->values[j].mask = ~0U;
                    654:       value = e;
                    655:     }
                    656: 
                    657:   *last_op = op;
                    658:   last_op = &op->next;
                    659:   op->next = NULL;
                    660: }
                    661: 
                    662: static void parse_ops(int argc, char **argv, int i)
                    663: {
                    664:   enum { STATE_INIT, STATE_GOT_FILTER, STATE_GOT_OP } state = STATE_INIT;
                    665:   struct pci_filter filter;
                    666:   struct pci_dev **selected_devices = NULL;
                    667: 
                    668:   while (i < argc)
                    669:     {
                    670:       char *c = argv[i++];
                    671: 
                    672:       if (*c == '-')
                    673:        {
                    674:          if (state != STATE_GOT_FILTER)
                    675:            pci_filter_init(pacc, &filter);
                    676:          i = parse_filter(argc, argv, i-1, &filter);
                    677:          state = STATE_GOT_FILTER;
                    678:        }
                    679:       else
                    680:        {
                    681:          if (state == STATE_INIT)
                    682:            parse_err("Filter specification expected");
                    683:          if (state == STATE_GOT_FILTER)
                    684:            selected_devices = select_devices(&filter);
                    685:          if (!selected_devices[0] && !force)
                    686:            fprintf(stderr, "setpci: Warning: No devices selected for \"%s\".\n", c);
                    687:          parse_op(c, selected_devices);
                    688:          state = STATE_GOT_OP;
                    689:        }
                    690:     }
                    691:   if (state == STATE_INIT)
                    692:     parse_err("No operation specified");
                    693: }
                    694: 
                    695: int
                    696: main(int argc, char **argv)
                    697: {
                    698:   int i;
                    699: 
                    700:   pacc = pci_alloc();
                    701:   pacc->error = die;
                    702:   i = parse_options(argc, argv);
                    703: 
                    704:   pci_init(pacc);
                    705:   pci_scan_bus(pacc);
                    706: 
                    707:   parse_ops(argc, argv, i);
                    708:   scan_ops(first_op);
                    709:   execute(first_op);
                    710: 
                    711:   return 0;
                    712: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>