Пример #1
0
// note: hd_data parameter is needed for ADD2LOG macro
void add_joystick_details(hd_data_t *hd_data, hd_t *h, const char *key, const char *abso)
{
  // replace existing details
  if (h->detail)
  {
    free_hd_detail(h->detail);
  }

  // add buttons and axis details
  h->detail = new_mem(sizeof *h->detail);
  h->detail->type = hd_detail_joystick;

  joystick_t *jt = new_mem(sizeof jt);
  unsigned u;

  if(key) {
    for(u = BTN_JOYSTICK; u < BTN_JOYSTICK + 16; u++) {
      if(test_bit(key, u)) jt->buttons++;
    }
  }
  ADD2LOG("  joystick buttons = %u\n", jt->buttons);

  if(abso) {
    for(u = ABS_X; u < ABS_VOLUME; u++) {
      if(test_bit(abso, u)) jt->axes++;
    }
  }
  ADD2LOG("  joystick axes = %u\n", jt->axes);

  h->detail->joystick.data = jt;
}
Пример #2
0
hd_t *hd_read_config(hd_data_t *hd_data, const char *id)
{
  hd_t *hd = NULL;
  hal_prop_t *prop = NULL;
  const char *udi = NULL;

  /* only of we didn't already (check internal db pointer) */
  /* prop2hd() makes db lookups */
  if(!hd_data->hddb2[1]) hddb_init(hd_data);

  if(id && *id == '/') {
    udi = id;
    id = NULL;
  }

  prop = read_properties(hd_data, udi, id);

  if(prop) {
    hd = new_mem(sizeof *hd);
    hd->idx = ++(hd_data->last_idx);
    hd->module = hd_data->module;
    hd->line = __LINE__;
    hd->tag.freeit = 1;		/* make it a 'stand alone' entry */
    hd->persistent_prop = prop;
    prop2hd(hd_data, hd, 0);
  }

  return hd;
}
Пример #3
0
/*
 * read an entry
 */
hal_prop_t *hd_manual_read_entry_old(const char *id)
{
  char path[PATH_MAX];
  int line;
  str_list_t *sl, *sl0;
  char *s, *s1, *s2;
  hal_prop_t *prop_list = NULL, *prop = NULL;

  if(!id) return NULL;

  snprintf(path, sizeof path, "%s/%s", hd_get_hddb_path("unique-keys"), id);

  if(!(sl0 = read_file(path, 0, 0))) return prop_list;

  for(line = 1, sl = sl0; sl; sl = sl->next, line++) {
    s = sl->str;
    while(isspace(*s)) s++;
    if(!*s || *s == '#' || *s == ';') continue;	/* empty lines & comments */

    s2 = s;
    s1 = strsep(&s2, "=");

    if(!s2 && *s == '[') continue;

    if(!s2) break;

    if(s1) {
      if(prop) {
        prop->next = new_mem(sizeof *prop);
        prop = prop->next;
      }
      else {
        prop_list = prop = new_mem(sizeof *prop);
      }

      prop->type = p_string;
      for(s = s1; *s; s++) if(*s >= 'A' && *s <= 'Z') *s += 'a' - 'A';
      str_printf(&prop->key, 0, "hwinfo.%s", s1);
      prop->val.str = canon_str(s2, strlen(s2));
    }
  }

  free_str_list(sl0);

  return prop_list;
}
Пример #4
0
void int_legacy_geo(hd_data_t *hd_data)
{
  hd_t *hd;
  hd_res_t *res;
  int id;
  char *s;
  edd_info_t *ei;

  if(!hd_data->edd) return;

  for(hd = hd_data->hd; hd; hd = hd->next) {
    if(
      hd->base_class.id == bc_storage_device &&
      hd->sub_class.id == sc_sdev_disk &&
      hd->rom_id
    ) {
      id = strtol(hd->rom_id, &s, 0) - 0x80;
      if(*s || id < 0 || id >= sizeof hd_data->edd / sizeof *hd_data->edd) continue;

      ei = hd_data->edd + id;

      if(ei->edd.cyls) {
        res = add_res_entry(&hd->res, new_mem(sizeof *res));
        res->disk_geo.type = res_disk_geo;
        res->disk_geo.cyls = ei->edd.cyls;
        res->disk_geo.heads = ei->edd.heads;
        res->disk_geo.sectors = ei->edd.sectors;
        res->disk_geo.size = ei->sectors;
        res->disk_geo.geotype = geo_bios_edd;
      }

      if(ei->legacy.cyls) {
        res = add_res_entry(&hd->res, new_mem(sizeof *res));
        res->disk_geo.type = res_disk_geo;
        res->disk_geo.cyls = ei->legacy.cyls;
        res->disk_geo.heads = ei->legacy.heads;
        res->disk_geo.sectors = ei->legacy.sectors;
        res->disk_geo.geotype = geo_bios_legacy;
      }

    }
  }
}
Пример #5
0
hal_prop_t *hal_get_new(hal_prop_t **list, const char *key)
{
  hal_prop_t *prop;

  prop = hal_get_any(*list, key);
  if(!prop) {
    prop = new_mem(sizeof *prop);
    prop->next = *list;
    *list = prop;
    prop->key = new_str(key);
  }
  else {
    hal_invalidate_all(prop, key);
  }

  return prop;
}
Пример #6
0
void prop2hd(hd_data_t *hd_data, hd_t *hd, int status_only)
{
  hal_prop_t *prop, *list;
  hd_res_t *res;
  int i;
  unsigned u, u0, u1, u2, u3, u4;
  char *s;
  uint64_t u64_0, u64_1;
  str_list_t *sl;

  list = hd->persistent_prop;

  hd->config_string = prop2hd_str(list, "hwinfo.configstring");

  if((prop = hal_get_str(list, "hwinfo.configured"))) {
    hd->status.configured = value2key(status_names, prop->val.str);
  }

  if((prop = hal_get_str(list, "hwinfo.available"))) {
    hd->status.available_orig =
    hd->status.available = value2key(status_names, prop->val.str);
  }

  if((prop = hal_get_str(list, "hwinfo.needed"))) {
    hd->status.needed = value2key(status_names, prop->val.str);
  }

  if((prop = hal_get_str(list, "hwinfo.active"))) {
    hd->status.active = value2key(status_names, prop->val.str);
  }

  /*
   * if the status info is completely missing, fake some:
   * new hardware, autodetectable, not needed
   */
  if(
    !hd->status.configured &&
    !hd->status.available &&
    !hd->status.needed &&
    !hd->status.invalid
  ) {
    hd->status.configured = status_new;
    hd->status.available = status_yes;
    hd->status.needed = status_no;
  }
  if(!hd->status.active) hd->status.active = status_unknown;

  if(status_only || !list) return;

  hd->udi = prop2hd_str(list, "info.udi");
  hd->unique_id = prop2hd_str(list, "hwinfo.uniqueid");
  hd->parent_id = prop2hd_str(list, "hwinfo.parentid");
  hd->child_ids = prop2hd_list(list, "hwinfo.childids");
  hd->model = prop2hd_str(list, "hwinfo.model");

  if((prop = hal_get_str(list, "hwinfo.hwclass"))) {
    hd->hw_class = value2key(hw_items, prop->val.str);
  }

  hd->broken = prop2hd_int32(list, "hwinfo.broken");

  hd->bus.id = prop2hd_int32(list, "hwinfo.busid");
  hd->slot = prop2hd_int32(list, "hwinfo.slot");
  hd->func = prop2hd_int32(list, "hwinfo.func");

  hd->base_class.id = prop2hd_int32(list, "hwinfo.baseclass");
  hd->sub_class.id = prop2hd_int32(list, "hwinfo.subclass");
  hd->prog_if.id = prop2hd_int32(list, "hwinfo.progif");

  hd->revision.id = prop2hd_int32(list, "hwinfo.revisionid");
  hd->revision.name = prop2hd_str(list, "hwinfo.revisionname");

  hd->vendor.id = prop2hd_int32(list, "hwinfo.vendorid");
  hd->vendor.name = prop2hd_str(list, "hwinfo.vendorname");

  hd->device.id = prop2hd_int32(list, "hwinfo.deviceid");
  hd->device.name = prop2hd_str(list, "hwinfo.devicename");

  hd->sub_vendor.id = prop2hd_int32(list, "hwinfo.subvendorid");
  hd->sub_vendor.name = prop2hd_str(list, "hwinfo.subvendorname");

  hd->sub_device.id = prop2hd_int32(list, "hwinfo.subdeviceid");
  hd->sub_device.name = prop2hd_str(list, "hwinfo.subdevicename");

  hd->compat_device.id = prop2hd_int32(list, "hwinfo.compatdeviceid");
  hd->compat_device.name = prop2hd_str(list, "hwinfo.compatdevicename");

  hd->serial = prop2hd_str(list, "hwinfo.serial");
  hd->unix_dev_name = prop2hd_str(list, "hwinfo.unixdevice");
  hd->unix_dev_name2 = prop2hd_str(list, "hwinfo.unixdevicealt");

  hd->unix_dev_names = prop2hd_list(list, "hwinfo.unixdevicelist");
  hd->drivers = prop2hd_list(list, "hwinfo.drivers");

  hd->sysfs_id = prop2hd_str(list, "hwinfo.sysfsid");
  hd->sysfs_bus_id = prop2hd_str(list, "hwinfo.sysfsbusid");
  hd->sysfs_device_link = prop2hd_str(list, "hwinfo.sysfslink");
  hd->rom_id = prop2hd_str(list, "hwinfo.romid");
  hd->usb_guid = prop2hd_str(list, "hwinfo.usbguid");
  hd->hotplug = prop2hd_int32(list, "hwinfo.hotplug");

  if((s = hal_get_useful_str(list, "hwinfo.hwclasslist"))) {
    for(u = 0; u < sizeof hd->hw_class_list / sizeof *hd->hw_class_list; u++) {
      if(*s && s[1] && (i = hex(s, 2)) >= 0) {
        hd->hw_class_list[u] = i;
        s += 2;
      }
      else {
        break;
      }
    }
  }

  u = prop2hd_int32(list, "hwinfo.features");
  if(u & (1 << 0)) hd->is.agp = 1;
  if(u & (1 << 1)) hd->is.isapnp = 1;
  if(u & (1 << 2)) hd->is.softraiddisk = 1;
  if(u & (1 << 3)) hd->is.zip = 1;
  if(u & (1 << 4)) hd->is.cdr = 1;
  if(u & (1 << 5)) hd->is.cdrw = 1;
  if(u & (1 << 6)) hd->is.dvd = 1;
  if(u & (1 << 7)) hd->is.dvdr = 1;
  if(u & (1 << 8)) hd->is.dvdram = 1;
  if(u & (1 << 9)) hd->is.pppoe = 1;
  if(u & (1 << 10)) hd->is.wlan = 1;


  if((prop = hal_get_list(list, "hwinfo.res.memory"))) {
    for(sl = prop->val.list; sl; sl = sl->next) {
      if(sscanf(sl->str, "0x%"SCNx64",0x%"SCNx64",%u,%u,%u", &u64_0, &u64_1, &u0, &u1, &u2) == 5) {
        res = add_res_entry(&hd->res, new_mem(sizeof *res));
        res->any.type = res_mem;
        res->mem.base = u64_0;
        res->mem.range = u64_1;
        res->mem.enabled = u0;
        res->mem.access = u1;
        res->mem.prefetch = u2;
      }
    }
  }

  if((prop = hal_get_list(list, "hwinfo.res.physmemory"))) {
    for(sl = prop->val.list; sl; sl = sl->next) {
      if(sscanf(sl->str, "0x%"SCNx64"", &u64_0) == 1) {
        res = add_res_entry(&hd->res, new_mem(sizeof *res));
        res->any.type = res_phys_mem;
        res->phys_mem.range = u64_0;
      }
    }
  }

  if((prop = hal_get_list(list, "hwinfo.res.io"))) {
    for(sl = prop->val.list; sl; sl = sl->next) {
      if(sscanf(sl->str, "0x%"SCNx64",0x%"SCNx64",%u,%u", &u64_0, &u64_1, &u0, &u1) == 4) {
        res = add_res_entry(&hd->res, new_mem(sizeof *res));
        res->any.type = res_io;
        res->io.base = u64_0;
        res->io.range = u64_1;
        res->io.enabled = u0;
        res->io.access = u1;
      }
    }
  }

  if((prop = hal_get_list(list, "hwinfo.res.interrupts"))) {
    for(sl = prop->val.list; sl; sl = sl->next) {
      if(sscanf(sl->str, "%u,%u,%u", &u0, &u1, &u2) == 3) {
        res = add_res_entry(&hd->res, new_mem(sizeof *res));
        res->any.type = res_irq;
        res->irq.base = u0;
        res->irq.triggered = u1;
        res->irq.enabled = u2;
      }
    }
  }

  if((prop = hal_get_list(list, "hwinfo.res.dma"))) {
    for(sl = prop->val.list; sl; sl = sl->next) {
      if(sscanf(sl->str, "%u,%u", &u0, &u1) == 2) {
        res = add_res_entry(&hd->res, new_mem(sizeof *res));
        res->any.type = res_dma;
        res->dma.base = u0;
        res->dma.enabled = u1;
      }
    }
  }

  if((prop = hal_get_list(list, "hwinfo.res.size"))) {
    for(sl = prop->val.list; sl; sl = sl->next) {
      if(sscanf(sl->str, "%u,%u,%u", &u0, &u1, &u2) == 3) {
        res = add_res_entry(&hd->res, new_mem(sizeof *res));
        res->any.type = res_size;
        res->size.unit = u0;
        res->size.val1 = u1;
        res->size.val2 = u2;
      }
    }
  }

  if((prop = hal_get_list(list, "hwinfo.res.baud"))) {
    for(sl = prop->val.list; sl; sl = sl->next) {
      if(sscanf(sl->str, "%u,%u,%u,%u,%u", &u0, &u1, &u2, &u3, &u4) == 5) {
        res = add_res_entry(&hd->res, new_mem(sizeof *res));
        res->any.type = res_baud;
        res->baud.speed = u0;
        res->baud.bits = u1;
        res->baud.stopbits = u2;
        res->baud.parity = (char) u3;
        res->baud.handshake = (char) u4;
      }
    }
  }

  if((prop = hal_get_list(list, "hwinfo.res.cache"))) {
    for(sl = prop->val.list; sl; sl = sl->next) {
      if(sscanf(sl->str, "%u", &u0) == 1) {
        res = add_res_entry(&hd->res, new_mem(sizeof *res));
        res->any.type = res_cache;
        res->cache.size = u0;
      }
    }
  }

  if((prop = hal_get_list(list, "hwinfo.res.diskgeometry"))) {
    for(sl = prop->val.list; sl; sl = sl->next) {
      if(sscanf(sl->str, "%u,%u,%u,%u", &u0, &u1, &u2, &u3) == 4) {
        res = add_res_entry(&hd->res, new_mem(sizeof *res));
        res->any.type = res_disk_geo;
        res->disk_geo.cyls = u0;
        res->disk_geo.heads = u1;
        res->disk_geo.sectors = u2;
        res->disk_geo.geotype = u3;
      }
    }
  }

  if((prop = hal_get_list(list, "hwinfo.res.monitor"))) {
    for(sl = prop->val.list; sl; sl = sl->next) {
      if(sscanf(sl->str, "%u,%u,%u,%u", &u0, &u1, &u2, &u3) == 4) {
        res = add_res_entry(&hd->res, new_mem(sizeof *res));
        res->any.type = res_monitor;
        res->monitor.width = u0;
        res->monitor.height = u1;
        res->monitor.vfreq = u2;
        res->monitor.interlaced = u3;
      }
    }
  }

  if((prop = hal_get_list(list, "hwinfo.res.framebuffer"))) {
    for(sl = prop->val.list; sl; sl = sl->next) {
      if(sscanf(sl->str, "%u,%u,%u,%u,%u", &u0, &u1, &u2, &u3, &u4) == 5) {
        res = add_res_entry(&hd->res, new_mem(sizeof *res));
        res->any.type = res_framebuffer;
        res->framebuffer.width = u0;
        res->framebuffer.height = u1;
        res->framebuffer.bytes_p_line = u2;
        res->framebuffer.colorbits = u3;
        res->framebuffer.mode = u4;
      }
    }
  }

  hddb_add_info(hd_data, hd);

}
Пример #7
0
/*
 * Get the (raw) PCI data, taken from /sys/bus/pci.
 *
 * Note: non-root users can only read the first 64 bytes (of 256)
 * of the device headers.
 */
void hd_pci_read_data(hd_data_t *hd_data)
{
  uint64_t ul0, ul1, ul2;
  unsigned u, u0, u1, u2, u3;
  unsigned char nxt;
  str_list_t *sl;
  char *s;
  pci_t *pci;
  int fd, i;
  str_list_t *sf_bus, *sf_bus_e;
  char *sf_dev;

  sf_bus = reverse_str_list(read_dir("/sys/bus/pci/devices", 'l'));

  if(!sf_bus) {
    ADD2LOG("sysfs: no such bus: pci\n");
    return;
  }

  for(sf_bus_e = sf_bus; sf_bus_e; sf_bus_e = sf_bus_e->next) {
    sf_dev = new_str(hd_read_sysfs_link("/sys/bus/pci/devices", sf_bus_e->str));

    ADD2LOG(
      "  pci device: name = %s\n    path = %s\n",
      sf_bus_e->str,
      hd_sysfs_id(sf_dev)
    );

    if(sscanf(sf_bus_e->str, "%x:%x:%x.%x", &u0, &u1, &u2, &u3) != 4) continue;

    pci = add_pci_entry(hd_data, new_mem(sizeof *pci));

    pci->sysfs_id = new_str(sf_dev);
    pci->sysfs_bus_id = new_str(sf_bus_e->str);

    pci->bus = (u0 << 8) + u1;
    pci->slot = u2;
    pci->func = u3;

    if((s = get_sysfs_attr_by_path(sf_dev, "modalias"))) {
      pci->modalias = canon_str(s, strlen(s));
      ADD2LOG("    modalias = \"%s\"\n", pci->modalias);
    }

    if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev, "class"), &ul0, 0)) {
      ADD2LOG("    class = 0x%x\n", (unsigned) ul0);
      pci->prog_if = ul0 & 0xff;
      pci->sub_class = (ul0 >> 8) & 0xff;
      pci->base_class = (ul0 >> 16) & 0xff;
    }

    if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev, "vendor"), &ul0, 0)) {
      ADD2LOG("    vendor = 0x%x\n", (unsigned) ul0);
      pci->vend = ul0 & 0xffff;
    }

    if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev, "device"), &ul0, 0)) {
      ADD2LOG("    device = 0x%x\n", (unsigned) ul0);
      pci->dev = ul0 & 0xffff;
    }

    if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev, "subsystem_vendor"), &ul0, 0)) {
      ADD2LOG("    subvendor = 0x%x\n", (unsigned) ul0);
      pci->sub_vend = ul0 & 0xffff;
    }

    if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev, "subsystem_device"), &ul0, 0)) {
      ADD2LOG("    subdevice = 0x%x\n", (unsigned) ul0);
      pci->sub_dev = ul0 & 0xffff;
    }

    if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev, "irq"), &ul0, 0)) {
      ADD2LOG("    irq = %d\n", (unsigned) ul0);
      pci->irq = ul0;
    }

    sl = hd_attr_list(get_sysfs_attr_by_path(sf_dev, "resource"));
    for(u = 0; sl; sl = sl->next, u++) {
      if(
        sscanf(sl->str, "0x%"SCNx64" 0x%"SCNx64" 0x%"SCNx64, &ul0, &ul1, &ul2) == 3 &&
        ul1 &&
        u < sizeof pci->base_addr / sizeof *pci->base_addr
      ) {
        ADD2LOG("    res[%u] = 0x%"PRIx64" 0x%"PRIx64" 0x%"PRIx64"\n", u, ul0, ul1, ul2);
        pci->base_addr[u] = ul0;
        pci->base_len[u] = ul1 + 1 - ul0;
        pci->addr_flags[u] = ul2;
      }
    }

    s = NULL;
    str_printf(&s, 0, "%s/config", sf_dev);
    if((fd = open(s, O_RDONLY)) != -1) {
      pci->data_len = pci->data_ext_len = read(fd, pci->data, 0x40);
      ADD2LOG("    config[%u]\n", pci->data_len);

      if(pci->data_len >= 0x40) {
        pci->hdr_type = pci->data[PCI_HEADER_TYPE] & 0x7f;
        pci->cmd = pci->data[PCI_COMMAND] + (pci->data[PCI_COMMAND + 1] << 8);

        if(pci->hdr_type == 1 || pci->hdr_type == 2) {	/* PCI or CB bridge */
          pci->secondary_bus = pci->data[PCI_SECONDARY_BUS];
          /* PCI_SECONDARY_BUS == PCI_CB_CARD_BUS */
        }

        for(u = 0; u < sizeof pci->base_addr / sizeof *pci->base_addr; u++) {
          if((pci->addr_flags[u] & IORESOURCE_IO)) {
            if(!(pci->cmd & PCI_COMMAND_IO)) pci->addr_flags[u] |= IORESOURCE_DISABLED;
          }

          if((pci->addr_flags[u] & IORESOURCE_MEM)) {
            if(!(pci->cmd & PCI_COMMAND_MEMORY)) pci->addr_flags[u] |= IORESOURCE_DISABLED;
          }
        }

        /* let's go through the capability list */
        if(
          pci->hdr_type == PCI_HEADER_TYPE_NORMAL &&
          (nxt = pci->data[PCI_CAPABILITY_LIST])
        ) {
          /*
           * Cut out after 16 capabilities to avoid infinite recursion due
           * to (potentially) malformed data. 16 is more or less
           * arbitrary, though (the capabilities are bits in a byte, so 8 entries
           * should suffice).
           */
          for(u = 0; u < 16 && nxt && nxt <= 0xfe; u++) {
            switch(pci_cfg_byte(pci, fd, nxt)) {
              case PCI_CAP_ID_PM:
                pci->flags |= (1 << pci_flag_pm);
                break;

              case PCI_CAP_ID_AGP:
                pci->flags |= (1 << pci_flag_agp);
                break;
            }
            nxt = pci_cfg_byte(pci, fd, nxt + 1);
          }
        }
      }

      close(fd);
    }

    str_printf(&s, 0, "%s/edid1", sf_dev);
    if((fd = open(s, O_RDONLY)) != -1) {
      pci->edid_len = read(fd, pci->edid, sizeof pci->edid);

      ADD2LOG("    edid[%u]\n", pci->edid_len);

      if(pci->edid_len > 0) {
        for(i = 0; i < sizeof pci->edid; i += 0x10) {
          ADD2LOG("      ");
          hexdump(&hd_data->log, 1, 0x10, pci->edid + i);
          ADD2LOG("\n");
        }
      }

      close(fd);
    }

    s = free_mem(s);

    pci->rev = pci->data[PCI_REVISION_ID];

    if((pci->addr_flags[6] & IORESOURCE_MEM)) {
      if(!(pci->data[PCI_ROM_ADDRESS] & PCI_ROM_ADDRESS_ENABLE)) {
        pci->addr_flags[6] |= IORESOURCE_DISABLED;
      }
    }

    pci->flags |= (1 << pci_flag_ok);

    free_mem(sf_dev);
  }
Пример #8
0
void hd_scan_pppoe(hd_data_t *hd_data2)
{
  hd_t *hd;
  int cnt, interfaces;
  PPPoEConnection *conn;

  hd_data = hd_data2;

  if(!hd_probe_feature(hd_data, pr_pppoe)) return;

  hd_data->module = mod_pppoe;

  PROGRESS(1, 0, "looking for pppoe");

  for(interfaces = 0, hd = hd_data->hd; hd; hd = hd->next) {
    if(
      hd->base_class.id == bc_network_interface &&
      hd->sub_class.id == sc_nif_ethernet &&
      hd->unix_dev_name
    ) {
      interfaces++;
    }
  }

  if(!interfaces) return;

  conn = new_mem(interfaces * sizeof *conn);

  for(cnt = 0, hd = hd_data->hd; hd && cnt < interfaces; hd = hd->next) {
    if(
      hd->base_class.id == bc_network_interface &&
      hd->sub_class.id == sc_nif_ethernet &&
      hd->unix_dev_name
    ) {
      conn[cnt].hd = hd;
      conn[cnt].fd = -1;
      conn[cnt].ifname = hd->unix_dev_name;
      cnt++;
    }
  }

  PROGRESS(2, 0, "discovery");

  discovery(interfaces, conn);

  for(cnt = 0; cnt < interfaces; cnt++) {
    conn[cnt].hd->is.pppoe = 0;

    if(conn[cnt].received_pado) {
      conn[cnt].hd->is.pppoe = 1;
      ADD2LOG(
        "pppoe %s: my mac %02x:%02x:%02x:%02x:%02x:%02x, "
        "peer mac %02x:%02x:%02x:%02x:%02x:%02x\n",
        conn[cnt].ifname,
        conn[cnt].my_mac[0], conn[cnt].my_mac[1], conn[cnt].my_mac[2],
        conn[cnt].my_mac[3], conn[cnt].my_mac[4], conn[cnt].my_mac[5],
        conn[cnt].peer_mac[0], conn[cnt].peer_mac[1], conn[cnt].peer_mac[2],
        conn[cnt].peer_mac[3], conn[cnt].peer_mac[4], conn[cnt].peer_mac[5]
      );
    }
  }
}
Пример #9
0
void add_serial_modem(hd_data_t *hd_data)
{
  hd_t *hd;
  char buf[4];
  ser_device_t *sm;
  hd_res_t *res;

  for(sm = hd_data->ser_modem; sm; sm = sm->next) {
    if(!sm->is_modem) continue;

    hd = hd_get_device_by_idx(hd_data, sm->hd_idx);
    if(hd && hd->base_class.id == bc_modem) {
      /* just *add* info */

    }
    else {
      hd = add_hd_entry(hd_data, __LINE__, 0);
      hd->base_class.id = bc_modem;
      hd->bus.id = bus_serial;
      hd->unix_dev_name = new_str(sm->dev_name);
      hd->attached_to = sm->hd_idx;
      res = add_res_entry(&hd->res, new_mem(sizeof *res));
      res->baud.type = res_baud;
      res->baud.speed = sm->max_baud;
      if(sm->pppd_option) {
	res = add_res_entry(&hd->res, new_mem(sizeof *res));
	res->pppd_option.type = res_pppd_option;
	res->pppd_option.option = new_str(sm->pppd_option);
      }
      if(*sm->pnp_id) {
        strncpy(buf, sm->pnp_id, 3);
        buf[3] = 0;
        hd->vendor.id = name2eisa_id(buf);
        hd->device.id = MAKE_ID(TAG_EISA, strtol(sm->pnp_id + 3, NULL, 16));
      }
      hd->serial = new_str(sm->serial);
      if(sm->user_name) hd->device.name = new_str(sm->user_name);
      if(sm->vend) hd->vendor.name = new_str(sm->vend);

      if(sm->dev_id && strlen(sm->dev_id) >= 7) {
        char buf[5], *s;
        unsigned u1, u2;

        u1 = name2eisa_id(sm->dev_id);
        if(u1) {
          strncpy(buf, sm->dev_id + 3, 4);
          buf[4] = 0;
          u2 = strtol(sm->dev_id + 3, &s, 16);
          if(!*s) {
            hd->compat_vendor.id = u1;
            hd->compat_device.id = MAKE_ID(TAG_EISA, u2);
          }
        }
      }

      if(!(hd->device.id || hd->device.name || hd->vendor.id || hd->vendor.name)) {
        hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x2000);
        hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0001);
      }
    }
    res = add_res_entry(&hd->res, new_mem(sizeof *res));
    res->init_strings.type = res_init_strings;
    res->init_strings.init1 = new_str(sm->init_string1);
    res->init_strings.init2 = new_str(sm->init_string2);
  }
}
Пример #10
0
void hd_scan_floppy(hd_data_t *hd_data)
{
  hd_t *hd;
  char b0[10], b1[10], c;
  unsigned u;
  int fd, i, floppy_ctrls = 0, floppy_ctrl_idx = 0;
  str_list_t *sl;
  hd_res_t *res;
  int floppy_stat[2] = { 1, 1 };
  unsigned floppy_created = 0;

  if(!hd_probe_feature(hd_data, pr_floppy)) return;

  hd_data->module = mod_floppy;

   /* some clean-up */
  remove_hd_entries(hd_data);
  hd_data->floppy = free_str_list(hd_data->floppy);

  PROGRESS(1, 0, "get nvram");

  /*
   * Look for existing floppy controller entries (typically there will be
   * *none*).
   */
  for(hd = hd_data->hd; hd; hd = hd->next) {
    if(hd->base_class.id == bc_storage && hd->sub_class.id == sc_sto_floppy) {
      floppy_ctrls++;
      floppy_ctrl_idx = hd->idx;
    }
  }

  /*
   * Is enough to load the nvram module.
   *
   * Note: although you must be root to access /dev/nvram, every
   * user can read /proc/nvram.
   */
  fd = open(DEV_NVRAM, O_RDONLY | O_NONBLOCK);
  if(fd >= 0) close(fd);

  if(
    !(hd_data->floppy = read_file(PROC_NVRAM_24, 0, 0)) &&
    !(hd_data->floppy = read_file(PROC_NVRAM_22, 0, 0))
  );

  if(hd_data->floppy && (hd_data->debug & HD_DEB_FLOPPY)) dump_floppy_data(hd_data);

  if(!hd_data->klog) read_klog(hd_data);

  for(sl = hd_data->klog; sl; sl = sl->next) {
    if(sscanf(sl->str, "<4>floppy%u: no floppy controllers foun%c", &u, &c) == 2) {
      if(u < sizeof floppy_stat / sizeof *floppy_stat) {
        floppy_stat[u] = 0;
      }
    }
  }

  if(hd_data->floppy) {
    PROGRESS(2, 0, "nvram info");
    sl = hd_data->floppy;
  }
  else {
    PROGRESS(2, 0, "klog info");
    sl = hd_data->klog;
  }

  for(; sl; sl = sl->next) {
    if(hd_data->floppy) {
      i = sscanf(sl->str, " Floppy %u type : %8[0-9.]'' %8[0-9.]%c", &u, b0, b1, &c) == 4;
    }
    else {
      i = sscanf(sl->str, "<6>Floppy drive(s): fd%u is %8[0-9.]%c", &u, b1, &c) == 3;
      *b0 = 0;
    }

    if(i) {
      if(
        !floppy_ctrls &&
        u < sizeof floppy_stat / sizeof *floppy_stat &&
        floppy_stat[u]
      ) {
        /* create one, if missing (there's no floppy without a controller...) */
        hd = add_hd_entry(hd_data, __LINE__, 0);
        hd->base_class.id = bc_storage;
        hd->sub_class.id = sc_sto_floppy;
        floppy_ctrl_idx = hd->idx;
        floppy_ctrls++;
      }

      if(floppy_ctrls && !(floppy_created & (1 << u))) {
        hd = add_hd_entry(hd_data, __LINE__, 0);
        hd->base_class.id = bc_storage_device;
        hd->sub_class.id = sc_sdev_floppy;
        hd->bus.id = bus_floppy;
        hd->slot = u;
        str_printf(&hd->unix_dev_name, 0, "/dev/fd%u", u);

        floppy_created |= 1 << u;

        if(*b0) {
          res = add_res_entry(&hd->res, new_mem(sizeof *res));
          res->size.type = res_size;
          res->size.val1 = str2float(b0, 2);
          res->size.unit = size_unit_cinch;
        }

        /* 'k' or 'M' */
        i = c == 'M' ? str2float(b1, 3) : str2float(b1, 0);

        res = add_res_entry(&hd->res, new_mem(sizeof *res));
        res->size.type = res_size;
        res->size.val1 = i << 1;
        res->size.val2 = 0x200;
        res->size.unit = size_unit_sectors;

        /* the only choice... */
        if(floppy_ctrls == 1) hd->attached_to = floppy_ctrl_idx;
      }
    }
  }
}
Пример #11
0
/*
 * Gather serial mouse data and put it into hd_data->ser_mouse.
 */
void get_serial_mouse(hd_data_t *hd_data)
{
  hd_t *hd;
  int j, fd, fd_max = 0, sel, max_len;
  unsigned modem_info;
  fd_set set, set0;
  struct timeval to;
  ser_device_t *sm;
  struct termios tio;

  FD_ZERO(&set);

  for(hd = hd_data->hd; hd; hd = hd->next) {
    if(
      hd->base_class.id == bc_comm &&
      hd->sub_class.id == sc_com_ser &&
      hd->unix_dev_name &&
      !hd->tag.ser_skip &&
      !has_something_attached(hd_data, hd)
    ) {
      if((fd = open(hd->unix_dev_name, O_RDWR | O_NONBLOCK)) >= 0) {
        if(tcgetattr(fd, &tio)) continue;
        sm = add_ser_mouse_entry(&hd_data->ser_mouse, new_mem(sizeof *sm));
        sm->dev_name = new_str(hd->unix_dev_name);
        sm->fd = fd;
        sm->tio = tio;
        sm->hd_idx = hd->idx;
        if(fd > fd_max) fd_max = fd;
        FD_SET(fd, &set);

        /*
         * PnP COM spec black magic...
         */
        setspeed(fd, 1200, 1, CS7);
        modem_info = TIOCM_DTR | TIOCM_RTS;
        ioctl(fd, TIOCMBIC, &modem_info);
      }
    }
  }

  if(!hd_data->ser_mouse) return;

  /*
   * 200 ms seems to be too fast for some mice...
   */
  usleep(300000);		/* PnP protocol */

  for(sm = hd_data->ser_mouse; sm; sm = sm->next) {
    modem_info = TIOCM_DTR | TIOCM_RTS;
    ioctl(sm->fd, TIOCMBIS, &modem_info);
  }

  /* smaller buffer size, otherwise we might wait really long... */
  max_len = sizeof sm->buf < 128 ? sizeof sm->buf : 128;

  to.tv_sec = 0; to.tv_usec = 300000;

  set0 = set;
  for(;;) {
   to.tv_sec = 0; to.tv_usec = 300000;
    set = set0;
    if((sel = select(fd_max + 1, &set, NULL, NULL, &to)) > 0) {
      for(sm = hd_data->ser_mouse; sm; sm = sm->next) {
        if(FD_ISSET(sm->fd, &set)) {
          if((j = read(sm->fd, sm->buf + sm->buf_len, max_len - sm->buf_len)) > 0)
            sm->buf_len += j;
          if(j <= 0) FD_CLR(sm->fd, &set0);	// #####
        }
      }
    }
    else {
      break;
    }
  }

  for(sm = hd_data->ser_mouse; sm; sm = sm->next) {
    chk4id(sm);
    /* reset serial lines */
    tcflush(sm->fd, TCIOFLUSH);
    tcsetattr(sm->fd, TCSAFLUSH, &sm->tio);
    close(sm->fd);
  }
}
Пример #12
0
/*
 * Read kernel log info. Combine with /var/log/boot.msg.
 */
void _read_klog(hd_data_t *hd_data)
{
  char buf[0x2000 + 1], *s;
  int i, j, len, n;
  str_list_t *sl, *sl1, *sl2, *sl_last, **ssl, *sl_next;

  /* some clean-up */
  hd_data->klog = free_str_list(hd_data->klog);

  sl1 = read_file(KLOG_BOOT, 0, 0);
  sl2 = NULL;

  /*
   * remove non-canonical lines (not starting with <[0-9]>) at the start and
   * at the end
   */

  /* note: the implementations assumes that at least *one* line is ok */
  for(sl_last = NULL, sl = sl1; sl; sl = (sl_last = sl)->next) {
    if(str_ok(sl)) {
      if(sl_last) {
        sl_last->next = NULL;
        free_str_list(sl1);
        sl1 = sl;
      }
      break;
    }
  }

  for(sl_last = NULL, sl = sl1; sl; sl = (sl_last = sl)->next) {
    if(!str_ok(sl)) {
      if(sl_last) {
        sl_last->next = NULL;
        free_str_list(sl);
      }
      break;
    }
  }

  n = klogctl(3, buf, sizeof buf - 1);
  if(n <= 0) {
    hd_data->klog = sl1;
    return;
  }

  if(n > (int) sizeof buf - 1) n = sizeof buf - 1;
  buf[n] = 0;
  for(i = j = 0; i < n; i++) {
    if(buf[i] == '\n') {
      len = i - j + 1;
      s = new_mem(len + 1);
      memcpy(s, buf + j, len);
      add_str_list(&sl2, s);
      s = free_mem(s);
      j = i + 1;
    }
  }

  /* the 1st line may be incomplete */
  if(sl2 && !str_ok(sl2)) {
    sl_next = sl2->next;
    sl2->next = NULL;
    free_str_list(sl2);
    sl2 = sl_next;
  }

  if(!sl1) {
    hd_data->klog = sl2;
    return;
  }

  if(sl1 && !sl2) {
    hd_data->klog = sl1;
    return;
  }

  /* now, try to join sl1 & sl2 */
  for(sl_last = NULL, sl = sl1; sl; sl = (sl_last = sl)->next) {
    if(!str_list_cmp(sl, sl2)) {
      free_str_list(sl);
      if(sl_last)
        sl_last->next = NULL;
      else
        sl1 = NULL;
      break;
    }
  }

  /* append sl2 to sl1 */
  for(ssl = &sl1; *ssl; ssl = &(*ssl)->next);
  *ssl = sl2;

  hd_data->klog = sl1;
}
Пример #13
0
void hd_scan_net(hd_data_t *hd_data)
{
  unsigned u;
  int if_type, if_carrier;
  hd_t *hd, *hd_card;
  char *s, *t, *hw_addr;
  hd_res_t *res, *res1, *res2;
  uint64_t ul0;
  str_list_t *sf_class, *sf_class_e;
  char *sf_cdev = NULL, *sf_dev = NULL;
  char *sf_drv_name, *sf_drv;

  if(!hd_probe_feature(hd_data, pr_net)) return;

  hd_data->module = mod_net;

  /* some clean-up */
  remove_hd_entries(hd_data);
  hd_data->net = free_str_list(hd_data->net);

  PROGRESS(1, 0, "get network data");

  sf_class = read_dir("/sys/class/net", 'l');
  if(!sf_class) sf_class = read_dir("/sys/class/net", 'd');

  if(!sf_class) {
    ADD2LOG("sysfs: no such class: net\n");
    return;
  }

  for(sf_class_e = sf_class; sf_class_e; sf_class_e = sf_class_e->next) {
    str_printf(&sf_cdev, 0, "/sys/class/net/%s", sf_class_e->str);

    hd_card = NULL;

    ADD2LOG(
      "  net interface: name = %s, path = %s\n",
      sf_class_e->str,
      hd_sysfs_id(sf_cdev)
    );

    if_type = -1;
    if(hd_attr_uint(get_sysfs_attr_by_path(sf_cdev, "type"), &ul0, 0)) {
      if_type = ul0;
      ADD2LOG("    type = %d\n", if_type);
    }

    if_carrier = -1;
    if(hd_attr_uint(get_sysfs_attr_by_path(sf_cdev, "carrier"), &ul0, 0)) {
      if_carrier = ul0;
      ADD2LOG("    carrier = %d\n", if_carrier);
    }

    hw_addr = NULL;
    if((s = get_sysfs_attr_by_path(sf_cdev, "address"))) {
      hw_addr = canon_str(s, strlen(s));
      ADD2LOG("    hw_addr = %s\n", hw_addr);
    }

    sf_dev = new_str(hd_read_sysfs_link(sf_cdev, "device"));
    if(sf_dev) {
      ADD2LOG("    net device: path = %s\n", hd_sysfs_id(sf_dev));
    }

    sf_drv_name = NULL;
    sf_drv = hd_read_sysfs_link(sf_dev, "driver");
    if(sf_drv) {
      sf_drv_name = strrchr(sf_drv, '/');
      if(sf_drv_name) sf_drv_name++;
      ADD2LOG(
        "    net driver: name = %s, path = %s\n",
        sf_drv_name,
        hd_sysfs_id(sf_drv)
      );
    }

    hd = add_hd_entry(hd_data, __LINE__, 0);
    hd->base_class.id = bc_network_interface;
    hd->sub_class.id = sc_nif_other;

    res1 = NULL;
    if(hw_addr && strspn(hw_addr, "0:") != strlen(hw_addr)) {
      res1 = new_mem(sizeof *res1);
      res1->hwaddr.type = res_hwaddr;
      res1->hwaddr.addr = new_str(hw_addr);
      add_res_entry(&hd->res, res1);
    }

    res2 = NULL;
    if(if_carrier >= 0) {
      res = new_mem(sizeof *res);
      res->link.type = res_link;
      res->link.state = if_carrier ? 1 : 0;
      add_res_entry(&hd->res, res);
    }

    hd->unix_dev_name = new_str(sf_class_e->str);
    hd->sysfs_id = new_str(hd_sysfs_id(sf_cdev));

    if(sf_drv_name) {
      add_str_list(&hd->drivers, sf_drv_name);
    }
    else if(hd->res) {
      get_driverinfo(hd_data, hd);
    }

    switch(if_type) {
      case ARPHRD_ETHER:	/* eth */
        hd->sub_class.id = sc_nif_ethernet;
        break;
      case ARPHRD_LOOPBACK:	/* lo */
        hd->sub_class.id = sc_nif_loopback;
        break;
      case ARPHRD_SIT:		/* sit */
        hd->sub_class.id = sc_nif_sit;
        break;
      case ARPHRD_FDDI:		/* fddi */
        hd->sub_class.id = sc_nif_fddi;
        break;
      case ARPHRD_IEEE802_TR:	/* tr */
        hd->sub_class.id = sc_nif_tokenring;
        break;
#if 0
      case ARPHRD_IEEE802:	/* fc */
        hd->sub_class.id = sc_nif_fc;
        break;
#endif
      default:
        hd->sub_class.id = sc_nif_other;
    }

    if(!strcmp(hd->unix_dev_name, "lo")) {
      hd->sub_class.id = sc_nif_loopback;
    }
    else if(sscanf(hd->unix_dev_name, "eth%u", &u) == 1) {
      hd->sub_class.id = sc_nif_ethernet;
      hd->slot = u;
    }
    else if(sscanf(hd->unix_dev_name, "tr%u", &u) == 1) {
      hd->sub_class.id = sc_nif_tokenring;
      hd->slot = u;
    }
    else if(sscanf(hd->unix_dev_name, "fddi%u", &u) == 1) {
      hd->sub_class.id = sc_nif_fddi;
      hd->slot = u;
    }
    else if(sscanf(hd->unix_dev_name, "ctc%u", &u) == 1) {
      hd->sub_class.id = sc_nif_ctc;
      hd->slot = u;
    }
    else if(sscanf(hd->unix_dev_name, "iucv%u", &u) == 1) {
      hd->sub_class.id = sc_nif_iucv;
      hd->slot = u;
    }
    else if(sscanf(hd->unix_dev_name, "hsi%u", &u) == 1) {
      hd->sub_class.id = sc_nif_hsi;
      hd->slot = u;
    }
    else if(sscanf(hd->unix_dev_name, "qeth%u", &u) == 1) {
      hd->sub_class.id = sc_nif_qeth;
      hd->slot = u;
    }
    else if(sscanf(hd->unix_dev_name, "escon%u", &u) == 1) {
      hd->sub_class.id = sc_nif_escon;
      hd->slot = u;
    }
    else if(sscanf(hd->unix_dev_name, "myri%u", &u) == 1) {
      hd->sub_class.id = sc_nif_myrinet;
      hd->slot = u;
    }
    else if(sscanf(hd->unix_dev_name, "sit%u", &u) == 1) {
      hd->sub_class.id = sc_nif_sit;	/* ipv6 over ipv4 tunnel */
      hd->slot = u;
    }
    else if(sscanf(hd->unix_dev_name, "wlan%u", &u) == 1) {
      hd->sub_class.id = sc_nif_wlan;
      hd->slot = u;
    }
    else if(sscanf(hd->unix_dev_name, "xp%u", &u) == 1) {
      hd->sub_class.id = sc_nif_xp;
      hd->slot = u;
    }
    else if(sscanf(hd->unix_dev_name, "usb%u", &u) == 1) {
      hd->sub_class.id = sc_nif_usb;
      hd->slot = u;
    }
    /* ##### add more interface names here */
    else {
      for(s = hd->unix_dev_name; *s; s++) if(isdigit(*s)) break;
      if(*s && (u = strtoul(s, &s, 10), !*s)) {
        hd->slot = u;
      }
    }

    hd->bus.id = bus_none;

    hd_card = NULL;

    if(sf_dev) {
      s = new_str(hd_sysfs_id(sf_dev));

      hd->sysfs_device_link = new_str(s);

      hd_card = hd_find_sysfs_id(hd_data, s);

      // try one above, if not found
      if(!hd_card) {
        t = strrchr(s, '/');
        if(t) {
          *t = 0;
          hd_card = hd_find_sysfs_id(hd_data, s);
        }
      }

      /* if one card has several interfaces (as with PS3), check interface names, too */
      if(
        hd_card &&
        hd_card->unix_dev_name &&
        hd->unix_dev_name &&
        strcmp(hd->unix_dev_name, hd_card->unix_dev_name)
      ) {
        hd_card = hd_find_sysfs_id_devname(hd_data, s, hd->unix_dev_name);
      }

      s = free_mem(s);

      if(hd_card) {
        hd->attached_to = hd_card->idx;

        /* for cards with strange pci classes */
        hd_set_hw_class(hd_card, hw_network_ctrl);

        /* add hw addr to network card */
        if(res1) {
          u = 0;
          for(res = hd_card->res; res; res = res->next) {
            if(
              res->any.type == res_hwaddr &&
              !strcmp(res->hwaddr.addr, res1->hwaddr.addr)
            ) {
              u = 1;
              break;
            }
          }
          if(!u) {
            res = new_mem(sizeof *res);
            res->hwaddr.type = res_hwaddr;
            res->hwaddr.addr = new_str(res1->hwaddr.addr);
            add_res_entry(&hd_card->res, res);
          }
        }
        /*
         * add interface names...
         * but not wmasterX (bnc #441778)
         */
        if(if_type != 801) add_if_name(hd_card, hd);
      }
    }

    if(!hd_card && hw_addr) {
      /* try to find card based on hwaddr (for prom-based cards) */

      for(hd_card = hd_data->hd; hd_card; hd_card = hd_card->next) {
        if(
          hd_card->base_class.id != bc_network ||
          hd_card->sub_class.id != 0
        ) continue;
        for(res = hd_card->res; res; res = res->next) {
          if(
            res->any.type == res_hwaddr &&
            !strcmp(hw_addr, res->hwaddr.addr)
          ) break;
        }
        if(res) {
          hd->attached_to = hd_card->idx;
          break;
        }
      }
    }

    hw_addr = free_mem(hw_addr);

    /* fix card type */
    if(hd_card) {
      if(
        (hd_card->base_class.id == 0 && hd_card->sub_class.id == 0) ||
        (hd_card->base_class.id == bc_network && hd_card->sub_class.id == 0x80)
      ) {
        switch(hd->sub_class.id) {
          case sc_nif_ethernet:
            hd_card->base_class.id = bc_network;
            hd_card->sub_class.id = 0;
            break;

          case sc_nif_usb:
            hd_card->base_class.id = bc_network;
            hd_card->sub_class.id = 0x91;
            break;
        }
      }
    }

    sf_dev = free_mem(sf_dev);
  }

  sf_cdev = free_mem(sf_cdev);
  sf_class = free_str_list(sf_class);

  if(hd_is_sgi_altix(hd_data)) add_xpnet(hd_data);
  add_uml(hd_data);
  add_kma(hd_data);

  /* add link status info & dump eeprom */
  for(hd = hd_data->hd ; hd; hd = hd->next) {
    if(
      hd->module == hd_data->module &&
      hd->base_class.id == bc_network_interface
    ) {
      char *buf = NULL;
      str_list_t *sl0, *sl;

      if(hd_probe_feature(hd_data, pr_net_eeprom) && hd->unix_dev_name) {
        PROGRESS(2, 0, "eeprom dump");

        str_printf(&buf, 0, "|/usr/sbin/ethtool -e %s 2>/dev/null", hd->unix_dev_name);
        if((sl0 = read_file(buf, 0, 0))) {
          ADD2LOG("----- %s %s -----\n", hd->unix_dev_name, "EEPROM dump");
          for(sl = sl0; sl; sl = sl->next) {
            ADD2LOG("%s", sl->str);
          }
          ADD2LOG("----- %s end -----\n", "EEPROM dump");
          free_str_list(sl0);
        }
        free(buf);
      }

      for(res = hd->res; res; res = res->next) {
        if(res->any.type == res_link) break;
      }

      if(!res) get_linkstate(hd_data, hd);

      if(!(hd_card = hd_get_device_by_idx(hd_data, hd->attached_to))) continue;

      for(res = hd->res; res; res = res->next) {
        if(res->any.type == res_link) break;
      }

      if(res) {
        for(res1 = hd_card->res; res1; res1 = res1->next) {
          if(res1->any.type == res_link) break;
        }
        if(res && !res1) {
          res1 = new_mem(sizeof *res1);
          res1->link.type = res_link;
          res1->link.state = res->link.state;
          add_res_entry(&hd_card->res, res1);
        }
      }
    }
  }
}
Пример #14
0
/*
 * read /proc/interrupts
 *
 * This is somewhat more tricky, as the irq event counts are done separately
 * per cpu *and* there may be irq sharing.
 */
void read_irqs(misc_t *m)
{
  char buf[100], buf2[100], *s;
  misc_irq_t *ir;
  int i, j;
  unsigned u, v, k;
  str_list_t *sl;

  if(!(m->proc_irq = read_file(PROC_INTERRUPTS, 1, 0))) return;

  for(sl = m->proc_irq; sl; sl = sl->next) {
    /* irq */
    i = 0;
    if(sscanf(sl->str, " %u: %n", &u, &i) < 1) continue;
    v = 0;
    j = i;
    /* add up all event counters */
    while(j < (int) strlen(sl->str) && sscanf(sl->str + j, " %u %n", &k, &i) >= 1) {
      if(!i) break;
      v += k;
      j += i;
    }
    /* device driver name string */
#if defined(__PPC__)
    if(
      sscanf(sl->str + j, " %*s Edge %99[^\n]", buf) == 1 ||
      sscanf(sl->str + j, " %*s Level %99[^\n]", buf) == 1 ||
      sscanf(sl->str + j, " %*s %99[^\n]", buf) == 1
    ) {
#else
#if defined(__alpha__) || defined(__sparc__)
    if(sscanf(sl->str + j, " %99[^\n]", buf) == 1) {
#else	/* __i386__ || __x86_64__ || __ia64__ */
    if(sscanf(sl->str + j, " %*s %99[^\n]", buf) == 1) {
#endif
#endif
      m->irq = add_mem(m->irq, sizeof *m->irq, m->irq_len);
      ir = m->irq + m->irq_len++;
      ir->irq = u;
      ir->events = v;

      /* split device driver names (separated by ',') */
      s = buf;
      while(*s && sscanf(s, " %99[^,] %n", buf2, &j) >= 1) {
        ir->dev = add_mem(ir->dev, sizeof *ir->dev, ir->devs);
        ir->dev[ir->devs++] = new_str(buf2);
        s += j;
        if(*s) s++;	/* skip ',' */
      }
    }
  }
}

void gather_resources(misc_t *m, hd_res_t **r, char *name, unsigned which)
{
  int i, j;
  hd_res_t *res;

  if(!m) return;

  if(!which) which = W_IO | W_DMA | W_IRQ;

  if((which & W_IO)) for(i = 0; (unsigned) i < m->io_len; i++) {
    if(!strcmp(name, m->io[i].dev)) {
      res = add_res_entry(r, new_mem(sizeof **r));
      res->io.type = res_io;
      res->io.enabled = 1;
      res->io.base = m->io[i].addr;
      res->io.range = m->io[i].size;
      res->io.access = acc_rw;
      m->io[i].tag++;
    }
  }

  if((which & W_DMA)) for(i = 0; (unsigned) i < m->dma_len; i++) {
    if(!strcmp(name, m->dma[i].dev)) {
      res = add_res_entry(r, new_mem(sizeof **r));
      res->dma.type = res_dma;
      res->dma.enabled = 1;
      res->dma.base = m->dma[i].channel;
      m->dma[i].tag++;
    }
  }

  if((which & W_IRQ)) for(i = 0; (unsigned) i < m->irq_len; i++) {
    for(j = 0; j <  m->irq[i].devs; j++) {
      if(!strcmp(name, m->irq[i].dev[j])) {
        res = add_res_entry(r, new_mem(sizeof **r));
        res->irq.type = res_irq;
        res->irq.enabled = 1;
        res->irq.base = m->irq[i].irq;
        res->irq.triggered = m->irq[i].events;
        m->irq[i].tag++;
      }
    }
  }
}


int active_vga_card(hd_t *hd)
{
  hd_res_t *res;

  if(hd->bus.id != bus_pci) return 1;

  for(res = hd->res; res; res = res->next) {
    if(
      (res->mem.type == res_mem && res->mem.enabled) ||
      (res->io.type == res_io && res->io.enabled)
    ) return 1;
  }

  return 0;
}
Пример #15
0
void hd_scan_misc(hd_data_t *hd_data)
{
  hd_t *hd;
  hd_res_t *res;
  int fd, i;
  char *s = NULL;
  bios_info_t *bt = NULL;
  char par[] = "parport0";
  int fd_ser0, fd_ser1;

  if(!hd_probe_feature(hd_data, pr_misc)) return;

  hd_data->module = mod_misc;

  /* some clean-up */
  remove_hd_entries(hd_data);
  hd_data->misc = free_misc(hd_data->misc);

  PROGRESS(9, 0, "kernel log");
  read_klog(hd_data);
  if((hd_data->debug & HD_DEB_MISC)) dump_klog(hd_data);

  PROGRESS(1, 0, "misc data");
  hd_data->misc = new_mem(sizeof *hd_data->misc);

  /* this is enough to load the module */
  fd_ser0 = fd_ser1 = -1;

#if !defined(__sparc__)
  /* On sparc, the close needs too long */
  if(hd_probe_feature(hd_data, pr_misc_serial)) {
    PROGRESS(1, 1, "open serial");
    fd_ser0 = open("/dev/ttyS0", O_RDONLY | O_NONBLOCK);
    fd_ser1 = open("/dev/ttyS1", O_RDONLY | O_NONBLOCK);
    /* keep the devices open until the resources have been read */
  }
#endif

  /* this is enough to load the module */
  if(!hd_data->flags.no_parport && hd_probe_feature(hd_data, pr_misc_par)) {
    PROGRESS(1, 2, "open parallel");
    /* what can the BIOS tell us? */
    for(hd = hd_data->hd; hd; hd = hd->next) {
      if(
        hd->base_class.id == bc_internal &&
        hd->sub_class.id == sc_int_bios &&
        hd->detail &&
        hd->detail->type == hd_detail_bios &&
        hd->detail->bios.data
      ) break;
    }
    if(hd) {
      bt = hd->detail->bios.data;
      if(bt->par_port0) {
        str_printf(&s, 0, "io=0x%x", bt->par_port0);
        if(bt->par_port1) {
          str_printf(&s, -1, ",0x%x", bt->par_port1);
          if(bt->par_port2) str_printf(&s, -1, ",0x%x", bt->par_port2);
        }
	str_printf(&s, -1, " irq=none,none,none");
      }
      unload_module(hd_data, "parport_probe");
      unload_module(hd_data, "lp");
      unload_module(hd_data, "parport_pc");
      unload_module(hd_data, "parport");

      /* now load it with the right io */
      load_module(hd_data, "parport");
      load_module_with_params(hd_data, "parport_pc", s);
      free_mem(s);
    }
    /* now load the rest of the modules */
    fd = open("/dev/lp0", O_RDONLY | O_NONBLOCK);
    if(fd >= 0) close(fd);
  }

  /*
   * floppy driver resources are allocated only temporarily,
   * so we access it just before we read the resources
   */
  if(hd_probe_feature(hd_data, pr_misc_floppy)) {
    /* look for a floppy *device* entry... */
    for(hd = hd_data->hd; hd; hd = hd->next) {
      if(
        hd->base_class.id == bc_storage_device &&
        hd->sub_class.id == sc_sdev_floppy &&
        hd->unix_dev_name &&
        !strncmp(hd->unix_dev_name, "/dev/fd", sizeof "/dev/fd" - 1)
      ) {

        PROGRESS(1, 3, "read floppy");
        i = 5;
        hd->block0 = read_block0(hd_data, hd->unix_dev_name, &i);
        hd->is.notready = hd->block0 ? 0 : 1;
        if(i < 0) {
          hd->tag.remove = 1;
          ADD2LOG("misc.floppy: removing floppy entry %u (timed out)\n", hd->idx);
        }

        if(!hd->is.notready) {
          struct hd_geometry geo;
          int fd;
          unsigned size, blk_size = 0x200;

          fd = open(hd->unix_dev_name, O_RDONLY | O_NONBLOCK);
          if(fd >= 0) {
            if(!ioctl(fd, HDIO_GETGEO, &geo)) {
              ADD2LOG("floppy ioctl(geo) ok\n");
              res = add_res_entry(&hd->res, new_mem(sizeof *res));
              res->disk_geo.type = res_disk_geo;
              res->disk_geo.cyls = geo.cylinders;
              res->disk_geo.heads = geo.heads;
              res->disk_geo.sectors = geo.sectors;
              res->disk_geo.geotype = geo_logical;
              size = geo.cylinders * geo.heads * geo.sectors;
              for(res = hd->res; res; res = res->next) {
                if(res->any.type == res_size && res->size.unit == size_unit_sectors) {
                  res->size.val1 = size; res->size.val2 = blk_size;
                  break;
                }
              }
              if(!res) {
                res = add_res_entry(&hd->res, new_mem(sizeof *res));
                res->size.type = res_size;
                res->size.unit = size_unit_sectors;
                res->size.val1 = size; res->size.val2 = blk_size;
              }
            }
            close(fd);
          }
        }

        break;
      }
    }
    remove_tagged_hd_entries(hd_data);
  }

  PROGRESS(2, 1, "io");
  read_ioports(hd_data->misc);

  PROGRESS(2, 2, "dma");
  read_dmas(hd_data->misc);

  PROGRESS(2, 3, "irq");
  read_irqs(hd_data->misc);

  if((hd_data->debug & HD_DEB_MISC)) dump_misc_proc_data(hd_data);

  if(fd_ser0 >= 0) close(fd_ser0);
  if(fd_ser1 >= 0) close(fd_ser1);

  /* now create some system generic entries */

  /* FPU */
  PROGRESS(3, 0, "FPU");
  res = NULL;
  gather_resources(hd_data->misc, &res, "fpu", 0);
  if(res) {
    hd = add_hd_entry(hd_data, __LINE__, 0);
    hd->base_class.id = bc_internal;
    hd->sub_class.id = sc_int_fpu;
    hd->res = res;
  }

  /* DMA */
  PROGRESS(3, 1, "DMA");
  res = NULL;
  gather_resources(hd_data->misc, &res, "dma1", 0);
  gather_resources(hd_data->misc, &res, "dma2", 0);
  gather_resources(hd_data->misc, &res, "dma page reg", 0);
  gather_resources(hd_data->misc, &res, "cascade", W_DMA);
  if(res) {
    hd = add_hd_entry(hd_data, __LINE__, 0);
    hd->base_class.id = bc_system;
    hd->sub_class.id = sc_sys_dma;
    hd->res = res;
  }

  /* PIC */
  PROGRESS(3, 2, "PIC");
  res = NULL;
  gather_resources(hd_data->misc, &res, "pic1", 0);
  gather_resources(hd_data->misc, &res, "pic2", 0);
  gather_resources(hd_data->misc, &res, "cascade", W_IRQ);
  if(res) {
    hd = add_hd_entry(hd_data, __LINE__, 0);
    hd->base_class.id = bc_system;
    hd->sub_class.id = sc_sys_pic;
    hd->res = res;
  }

  /* timer */
  PROGRESS(3, 3, "timer");
  res = NULL;
  gather_resources(hd_data->misc, &res, "timer", 0);
  if(res) {
    hd = add_hd_entry(hd_data, __LINE__, 0);
    hd->base_class.id = bc_system;
    hd->sub_class.id = sc_sys_timer;
    hd->res = res;
  }

  /* real time clock */
  PROGRESS(3, 4, "RTC");
  res = NULL;
  gather_resources(hd_data->misc, &res, "rtc", 0);
  if(res) {
    hd = add_hd_entry(hd_data, __LINE__, 0);
    hd->base_class.id = bc_system;
    hd->sub_class.id = sc_sys_rtc;
    hd->res = res;
  }

  /* keyboard */
  res = NULL;
  gather_resources(hd_data->misc, &res, "keyboard", 0);
  if(res) {
    hd = add_hd_entry(hd_data, __LINE__, 0);
    hd->base_class.id = bc_input;
    hd->sub_class.id = sc_inp_keyb;
    hd->res = res;
  }

  /* parallel ports */
  for(i = 0; i < 1; i++, par[sizeof par - 2]++) {
    res = NULL;
    gather_resources(hd_data->misc, &res, par, 0);
    if(res) {
      hd = add_hd_entry(hd_data, __LINE__, 0);
      hd->base_class.id = bc_comm;
      hd->sub_class.id = sc_com_par;
      str_printf(&hd->unix_dev_name, 0, "/dev/lp%d", i);
      hd->res = res;
    }
  }

  /* floppy controller */
  res = NULL;
  gather_resources(hd_data->misc, &res, "floppy", 0);
  gather_resources(hd_data->misc, &res, "floppy DIR", 0);
  if(res) {
    /* look for an existing entry */
    for(hd = hd_data->hd; hd; hd = hd->next) {
      if(hd->base_class.id == bc_storage && hd->sub_class.id == sc_sto_floppy) break;
    }

    /* missing, so create one */
    if(!hd) {
      hd = add_hd_entry(hd_data, __LINE__, 0);
      hd->base_class.id = bc_storage;
      hd->sub_class.id = sc_sto_floppy;
    }

    hd->res = res;
  }

  /*
   * look for PS/2 port
   *
   * The catch is, that sometimes /dev/psaux is accessible only for root,
   * so the open() may fail but there are irq events registered.
   *
   */
  fd = open(DEV_PSAUX, O_RDONLY | O_NONBLOCK);
  if(fd >= 0) close(fd);

  res = NULL;
  gather_resources(hd_data->misc, &res, "PS/2 Mouse", 0);

  if(res || fd >= 0) {
    hd = add_hd_entry(hd_data, __LINE__, 0);
    hd->base_class.id = bc_ps2;

    if(res) {
      hd->res = res;
    }
  }
}
Пример #16
0
void hd_scan_misc2(hd_data_t *hd_data)
{
  hd_t *hd, *hd1;
  misc_t *m;
  hd_res_t *res, *res1, *res2;
  int i;

  if(!hd_probe_feature(hd_data, pr_misc)) return;

  hd_data->module = mod_misc;

  PROGRESS(5, 0, "misc data");

  /* create some more system generic entries */

  /* IDE */

// ###### add special ide detail to hd_t!!!
  res = NULL;
  gather_resources(hd_data->misc, &res, "ide0", 0);
  gather_resources(hd_data->misc, &res, "ide1", 0);
  gather_resources(hd_data->misc, &res, "ide2", 0);
  gather_resources(hd_data->misc, &res, "ide3", 0);
  if(res) {
    for(hd = hd_data->hd; hd; hd = hd->next) {
      if(
        hd->base_class.id == bc_storage &&
        hd->sub_class.id == sc_sto_ide &&
        have_common_res(hd->res, res)
      ) break;
    }
    if(!hd) {
      /* eg. non-PCI IDE controller */
      hd = add_hd_entry(hd_data, __LINE__, 0);
      hd->base_class.id = bc_storage;
      hd->sub_class.id = sc_sto_ide;
      hd->compat_vendor.id = MAKE_ID(TAG_SPECIAL, 0x3000);
      hd->compat_device.id = MAKE_ID(TAG_SPECIAL, 0x1000);
      /* use join_res to join the i/o ranges of ide0/1 */
      join_res_io(&hd->res, res);
      join_res_irq(&hd->res, res);
      join_res_dma(&hd->res, res);
      free_res_list(res);
    }
    else {
      /* eg. PCI IDE controller, add resources */
      join_res_io(&hd->res, res);
      join_res_irq(&hd->res, res);
      join_res_dma(&hd->res, res);
      free_res_list(res);
    }
  }

  /* VGA */
  res = NULL;
  gather_resources(hd_data->misc, &res, "vga+", 0);
  gather_resources(hd_data->misc, &res, "vesafb", 0);
  if(res) {
    for(i = 0, hd1 = NULL, hd = hd_data->hd; hd; hd = hd->next) {
      if(hd->base_class.id == bc_display && hd->sub_class.id == sc_dis_vga) {
        i++;
        hd1 = hd;
      }
    }
    if(i == 0) {
      /* non-PCI VGA card ??? - really, we shouldn't care... */
      /* FIX THIS !!! ############### */
#ifdef __alpha__
      free_res_list(res);
#else
      hd = add_hd_entry(hd_data, __LINE__, 0);
      hd->base_class.id = bc_display;
      hd->sub_class.id = sc_dis_vga;
      hd->res = res;
#endif
    }
    else if(i == 1) {
      /* 1 PCI vga card, add resources */
      join_res_io(&hd1->res, res);
      join_res_irq(&hd1->res, res);
      join_res_dma(&hd1->res, res);
      free_res_list(res);
      hd_data->display = hd1->idx;
    }
    else {
      /* more than 1: look again, now only 'active' cards */
      for(i = 0, hd1 = NULL, hd = hd_data->hd; hd; hd = hd->next) {
        if(
          hd->base_class.id == bc_display &&
          hd->sub_class.id == sc_dis_vga &&
          active_vga_card(hd)
        ) {
          i++;
          hd1 = hd;
        }
      }
      if(i == 1) {
        /* 'the' active PCI vga card, add resources */
        join_res_io(&hd1->res, res);
        join_res_irq(&hd1->res, res);
        join_res_dma(&hd1->res, res);
        hd_data->display = hd1->idx;
      }
      else {
       /* now, what??? */
       ADD2LOG("Oopy, could not figure out *the* active display adapter!\n");
      }
      free_res_list(res);
    }
  }

  /* serial ports */
  res = NULL;
  gather_resources(hd_data->misc, &res, "serial(auto)", 0);
  gather_resources(hd_data->misc, &res, "serial(set)", 0);
  gather_resources(hd_data->misc, &res, "serial", 0);
  for(hd = hd_data->hd; hd; hd = hd->next) {
    if(hd->base_class.id == bc_comm && hd->sub_class.id == sc_com_ser) {
      for(res1 = hd->res; res1; res1 = res1->next) {
        for(res2 = res; res2; res2 = res2->next) {
          if(res1->any.type == res2->any.type) {
            switch(res1->any.type) {
              case res_irq:
                if(res1->irq.base == res2->irq.base) {
                  res2->any.type = res_any;
                }
                break;
              case res_io:
                if(
                  res1->io.base == res2->io.base &&
                  (!res1->io.range || res1->io.range == res2->io.range)
                ) {
                  res1->io.range = res2->io.range;
                  res2->any.type = res_any;
                }
                break;
              default:		/* gcc -Wall */
		break;
            }
          }
        }
      }
    }
  }

  /* if any of the serial resources are unaccounted for, make an extra entry */
  for(res2 = res; res2; res2 = res2->next) {
    if(res2->any.type != res_any) {
      hd = add_hd_entry(hd_data, __LINE__, 0);
      hd->base_class.id = bc_comm;
      hd->sub_class.id = sc_com_ser;
      hd->prog_if.id = 0x80;
      for(; res2; res2 = res2->next) {
        if(res2->any.type != res_any) {
          res1 = add_res_entry(&hd->res, new_mem(sizeof *res));
          *res1 = *res2;
          res1->next = NULL;
        }
      }
      break;
    }
  }
  free_res_list(res);

  /* go through our list and assign event counts to irq entries */
  m = hd_data->misc;
  for(hd = hd_data->hd; hd; hd = hd->next) {
    for(res = hd->res; res; res = res->next) {
      if(res->irq.type == res_irq) {
        for(i = 0; (unsigned) i < m->irq_len; i++) {
          if(res->irq.base == m->irq[i].irq) {
            res->irq.triggered = m->irq[i].events;
            break;
          }
        }
      }
    }
  }

  /* look for entries with matching start address */
  m = hd_data->misc;
  for(hd = hd_data->hd; hd; hd = hd->next) {
    for(res = hd->res; res; res = res->next) {
      if(res->io.type == res_io) {
        for(i = 0; (unsigned) i < m->io_len; i++) {
          if(res->io.base == m->io[i].addr && res->io.range < m->io[i].size) {
            res->io.range = m->io[i].size;
            break;
          }
        }
      }
    }
  }

  if((hd_data->debug & HD_DEB_MISC)) dump_misc_data(hd_data);
}
Пример #17
0
void int_bios(hd_data_t *hd_data)
{
  hd_t *hd, *hd_boot;
  unsigned *sctrl, *sctrl2;
  int sctrl_len, i, j;
  int bios_id, list_sorted;

  /* don't do anything if there is useful edd info */
  if(hd_data->flags.edd_used) return;

  for(i = 0, hd = hd_data->hd; hd; hd = hd->next) {
    if(
      hd->base_class.id == bc_storage_device &&
      hd->sub_class.id == sc_sdev_disk
    ) {
      i++;
    }
  }

  if(!i) return;

  sctrl = new_mem(i * sizeof *sctrl);

  /* sctrl: list of storage controllers with disks */

  for(sctrl_len = 0, hd = hd_data->hd; hd; hd = hd->next) {
    if(
      hd->base_class.id == bc_storage_device &&
      hd->sub_class.id == sc_sdev_disk
    ) {
      for(i = 0; i < sctrl_len; i++) {
        if(sctrl[i] == hd->attached_to) break;
      }
      if(i == sctrl_len) sctrl[sctrl_len++] = hd->attached_to;
    }
  }

  /* sort list, if possible */

  list_sorted = bios_ctrl_order(hd_data, sctrl, sctrl_len);

  hd_boot = hd_get_device_by_idx(hd_data, hd_boot_disk(hd_data, &i));

  /* if we know the boot device, make this controller the first */

  if(hd_boot && hd_boot->attached_to && i == 1) {
    for(i = 0; i < sctrl_len; i++) {
      if(sctrl[i] == hd_boot->attached_to) break;
    }
    if(i < sctrl_len) {
      sctrl2 = new_mem(sctrl_len * sizeof *sctrl2);
      *sctrl2 = hd_boot->attached_to;
      for(i = 0, j = 1; i < sctrl_len; i++) {
        if(sctrl[i] != hd_boot->attached_to) sctrl2[j++] = sctrl[i];
      }
      free_mem(sctrl);
      sctrl = sctrl2;
    }
  }
  else {
    hd_boot = NULL;
  }

  if(hd_boot) ADD2LOG("  bios boot dev: %d\n", hd_boot->idx);
  for(i = 0; i < sctrl_len; i++) {
    ADD2LOG("  bios ctrl %d: %d\n", i, sctrl[i]);
  }

  /* remove existing entries */

  for(hd = hd_data->hd; hd; hd = hd->next) {
    if(
      hd->base_class.id == bc_storage_device &&
      hd->sub_class.id == sc_sdev_disk
    ) {
      hd->rom_id = free_mem(hd->rom_id);
    }
  }

  if(!list_sorted && !hd_boot && sctrl_len > 1) {
    /* we have no info at all */
    sctrl_len = 0;
  }
  else if(!list_sorted && hd_boot && sctrl_len > 2) {
    /* we know which controller has the boot device */
    sctrl_len = 1;
  }

  bios_id = 0x80;

  /* rely on it */

  if(hd_boot) {
    bios_id += set_bios_id(hd_data, hd_boot, bios_id);
  }

  /* assign all the others */

  for(i = 0; i < sctrl_len; i++) {
    for(hd = hd_data->hd; hd; hd = hd->next) {
      if(
        hd->base_class.id == bc_storage_device &&
        hd->sub_class.id == sc_sdev_disk &&
        hd->attached_to == sctrl[i] &&
        !hd->rom_id
      ) {
        bios_id += set_bios_id(hd_data, hd, bios_id);
      }
    }
  }

  free_mem(sctrl);
}
Пример #18
0
void get_serial_info(hd_data_t *hd_data)
{
  char buf[64];
  unsigned u0, u1, u2;
#if !defined(__PPC__)
  unsigned u3;
#endif
  int i;
  str_list_t *sl, *sl0, **sll;
  serial_t *ser;

#if !defined(__PPC__)
  /*
   * Max. 44 serial lines at the moment; the serial proc interface is
   * somewhat buggy at the moment (2.2.13), hence the explicit 44 lines
   * limit. That may be dropped later.
   */
  sl0 = read_file(PROC_DRIVER_SERIAL, 1, 44);
  sll = &sl0;
  while(*sll) sll = &(*sll)->next;
  // append Agere modem devices
  *sll = read_file("/proc/tty/driver/agrserial", 1, 17);


  // ########## FIX !!!!!!!! ########
  if(sl0) {
    for(sl = sl0; sl; sl = sl->next) {
      i = 0;
      if(
        sscanf(sl->str, "%u: uart:%31s port:%x irq:%u baud:%u", &u0, buf, &u1, &u2, &u3) == 5 ||
        (i = 1, sscanf(sl->str, "%u: uart:%31s port:%x irq:%u tx:%u", &u0, buf, &u1, &u2, &u3) == 5)
      ) {
        /*
         * The 'baud' or 'tx' entries are only present for real interfaces.
         */
        ser = add_serial_entry(&hd_data->serial, new_mem(sizeof *ser));
        ser->line = u0;
        if(u1 >= 0x100) ser->port = u1;		// Agere modem does not use real port numbers
        ser->irq = u2;
        if(!i) ser->baud = u3;
        ser->name = new_str(buf);
      }
    }

    if((hd_data->debug & HD_DEB_SERIAL)) {
      /* log just the first 16 entries */
      ADD2LOG("----- "PROC_DRIVER_SERIAL" -----\n");
      for(sl = sl0, i = 16; sl && i--; sl = sl->next) {
        ADD2LOG("  %s", sl->str);
      }
      ADD2LOG("----- "PROC_DRIVER_SERIAL" end -----\n");
    }
  }
#endif	/* !defined(__PPC__) */

#if defined(__PPC__)
  sl0 = read_file(PROC_DRIVER_MACSERIAL, 1, 0);

  if(sl0) {
    for(sl = sl0; sl; sl = sl->next) {
      if(
        (i = sscanf(sl->str, "%u: port:%x irq:%u con:%63[^\n]", &u0, &u1, &u2, buf)) >= 3
      ) {
        ser = add_serial_entry(&hd_data->serial, new_mem(sizeof *ser));
        ser->line = u0;
        ser->port = u1;
        ser->irq = u2;
        ser->name = new_str("SCC");
        if(i == 4) ser->device = new_str(buf);
      }
    }

    if((hd_data->debug & HD_DEB_SERIAL)) {
      /* log just the first 16 entries */
      ADD2LOG("----- "PROC_DRIVER_MACSERIAL" -----\n");
      for(sl = sl0, i = 16; sl && i--; sl = sl->next) {
        ADD2LOG("  %s", sl->str);
      }
      ADD2LOG("----- "PROC_DRIVER_MACSERIAL" end -----\n");
    }
  }
#endif	/* defined(__PPC__) */


  free_str_list(sl0);
}
Пример #19
0
void hd_scan_wlan(hd_data_t *hd_data)
{
  hd_t *hd;
  hd_res_t *res;
  struct iw_range range;
  int k;
  int skfd;
  struct wpa_driver_ops *wpa_drv=NULL;

  if(!hd_probe_feature(hd_data, pr_wlan)) return;

  hd_data->module = mod_wlan;

  PROGRESS(1, 0, "detecting wlan features");

  if ((skfd = iw_sockets_open()) < 0) {
    ADD2LOG( "could not open socket, wlan feature query failed\n" );
    return;
  }

  for(hd = hd_data->hd; hd; hd = hd->next) {
    if(
      hd->base_class.id == bc_network &&
      hd->unix_dev_name ) {
      /* Get list of frequencies / channels */
      if(iw_get_range_info(skfd, hd->unix_dev_name, &range) < 0) {
	/* this failed, maybe device does not support wireless extensions */
	continue;
      }
      ADD2LOG("*** device %s is wireless ***\n", hd->unix_dev_name);
      hd->is.wlan = 1;

      hd->sub_class.id = 0x82;		/* wlan */

      res = new_mem(sizeof *res);
      res->any.type = res_wlan;

      if(range.num_frequency > 0) {
	char buff[20];
	for(k = 0; k < range.num_frequency; k++) {
	  snprintf(buff, 19, "%i", range.freq[k].i);
	  add_str_list(&res->wlan.channels, buff);
	  snprintf(buff, 19, "%g", (float)iw_freq2float(&(range.freq[k]))/1000000000);
	  add_str_list(&res->wlan.frequencies, buff);
	}
	for(k = 0; k < range.num_bitrates; k++) {
	  snprintf(buff, 19, "%g", (float)range.bitrate[k]/1000000);
	  add_str_list(&res->wlan.bitrates, buff);
	}
	for(k = 0; k < range.num_encoding_sizes; k++) {
	  snprintf(buff, 19, "WEP%i", range.encoding_size[k]*8);
	  add_str_list(&res->wlan.enc_modes, buff);
	}

	/* open mode is always supported */
	add_str_list(&res->wlan.auth_modes, "open");
	/* if WEP is supported, be assume shared key auth support */
	if(range.num_encoding_sizes) {
	  add_str_list(&res->wlan.auth_modes, "sharedkey");
	}

	/* detect WPA capabilities */
	if (!hd_data->flags.nowpa && hd->drivers) {
	  if (search_str_list(hd->drivers, "ath_pci"))
	    wpa_drv = &wpa_driver_madwifi_ops;
	  else if (strncmp(hd->drivers->str, "at76", 4)==0)
	    wpa_drv = &wpa_driver_atmel_ops;
	  else 
	    wpa_drv = &wpa_driver_wext_ops;
	}
	
	if (wpa_drv) {
	  if (wpa_drv->set_wpa(hd->unix_dev_name, 1) == 0) {
	    add_str_list(&res->wlan.auth_modes, "wpa-psk");
	    add_str_list(&res->wlan.auth_modes, "wpa-eap");
	    if (wpa_drv->set_auth_alg && 
		wpa_drv->set_auth_alg(hd->unix_dev_name, AUTH_ALG_LEAP)==0)
	      add_str_list(&res->wlan.auth_modes, "wpa-leap");
	    if (wpa_drv->set_key(hd->unix_dev_name, WPA_ALG_TKIP, "ff:ff:ff:ff:ff:ff",
				 0, 0, 0, 0,
				 "00000000000000000000000000000000", 32) ==0)
	      add_str_list(&res->wlan.enc_modes, "TKIP");
	    if (wpa_drv->set_key(hd->unix_dev_name, WPA_ALG_CCMP, "ff:ff:ff:ff:ff:ff",
				 0, 0, 0, 0, 
				 "0000000000000000", 16) ==0)
	      add_str_list(&res->wlan.enc_modes, "CCMP");
	    wpa_drv->set_wpa(hd->unix_dev_name, 0);
	  }
	}
      }
      add_res_entry(&hd->res, res);
    }
  }
}
Пример #20
0
int bios_ctrl_order(hd_data_t *hd_data, unsigned *sctrl, int sctrl_len)
{
  hd_t *hd;
  bios_info_t *bt;
  int i, j, k, sctrl2_len = 0;
  unsigned pci_slot, pci_func;
  unsigned *sctrl2 = NULL, *sctrl3 = NULL;
  int order_info = 0;

  for(bt = NULL, hd = hd_data->hd; hd; hd = hd->next) {
    if(
      hd->base_class.id == bc_internal &&
      hd->sub_class.id == sc_int_bios &&
      hd->detail &&
      hd->detail->type == hd_detail_bios &&
      (bt = hd->detail->bios.data)
    ) {
      break;
    }
  }

  if(!bt || !bt->bios32.ok || !bt->bios32.compaq) return 0;

  sctrl2 = new_mem((sizeof bt->bios32.cpq_ctrl / sizeof *bt->bios32.cpq_ctrl) * sizeof *sctrl2);

  for(i = 0; (unsigned) i < sizeof bt->bios32.cpq_ctrl / sizeof *bt->bios32.cpq_ctrl; i++) {
    if(
      bt->bios32.cpq_ctrl[i].id &&
      !(bt->bios32.cpq_ctrl[i].misc & 0x40)	/* bios support ??????? */
    ) {
      pci_slot = PCI_SLOT(bt->bios32.cpq_ctrl[i].devfn) + (bt->bios32.cpq_ctrl[i].bus << 8);
      pci_func = PCI_FUNC(bt->bios32.cpq_ctrl[i].devfn);
      for(hd = hd_data->hd; hd; hd = hd->next) {
        if(hd->bus.id == bus_pci && hd->slot == pci_slot && hd->func == pci_func) {
          sctrl2[sctrl2_len++] = hd->idx;
          break;
        }
      }
    }
  }

  if(sctrl2_len) order_info = 1;

  for(i = 0; i < sctrl2_len; i++) {
    ADD2LOG("  bios ord %d: %d\n", i, sctrl2[i]);
  }

  /* sort list */

  sctrl3 = new_mem(sctrl_len * sizeof *sctrl3);

  k = 0 ;
  for(i = 0; i < sctrl2_len; i++) {
    for(j = 0; j < sctrl_len; j++) {
      if(sctrl[j] == sctrl2[i]) {
        sctrl3[k++] = sctrl[j];
        sctrl[j] = 0;
        break;
      }
    }
  }

  for(i = 0; i < sctrl_len; i++) {
    if(sctrl[i] && k < sctrl_len) sctrl3[k++] = sctrl[i];
  }

  memcpy(sctrl, sctrl3, sctrl_len * sizeof *sctrl);

  free_mem(sctrl2);
  free_mem(sctrl3);

  return order_info;
}
Пример #21
0
void hd_scan_serial(hd_data_t *hd_data)
{
  hd_t *hd, *hd2;
  serial_t *ser, *next;
  hd_res_t *res, *res2;
  int i;
  char buf[4], *skip_dev[16];
  str_list_t *sl, *cmd;
  unsigned skip_devs = 0;

  if(!hd_probe_feature(hd_data, pr_serial)) return;

  hd_data->module = mod_serial;

  /* some clean-up */
  remove_hd_entries(hd_data);
  hd_data->serial = NULL;

  PROGRESS(1, 0, "read info");

  get_serial_info(hd_data);
  if((hd_data->debug & HD_DEB_SERIAL)) dump_serial_data(hd_data);

  for(i = 0; i < 2; i++) {
    cmd = get_cmdline(hd_data, i == 0 ? "yast2ser" : "console");
    for(sl = cmd; sl; sl = sl->next) {
      if(sscanf(sl->str, "tty%3[^,]", buf) == 1) {
        if(buf[1] == 0) {
          switch(*buf) {
            case 'a': strcpy(buf, "S0"); break;
            case 'b': strcpy(buf, "S1"); break;
          }
        }
        if(skip_devs < sizeof skip_dev / sizeof *skip_dev) {
          skip_dev[skip_devs] = NULL;
          str_printf(&skip_dev[skip_devs++], 0, "/dev/tty%s", buf);
        }
      }
    }
    free_str_list(cmd);
  }

  PROGRESS(2, 0, "build list");

  for(ser = hd_data->serial; ser; ser = ser->next) {
    hd = add_hd_entry(hd_data, __LINE__, 0);
    hd->base_class.id = bc_comm;
    hd->sub_class.id = sc_com_ser;
    hd->prog_if.id = 0x80;
    for(i = 0; (unsigned) i < sizeof ser_names / sizeof *ser_names; i++) {
      if(strstr(ser->name, ser_names[i])) hd->prog_if.id = i;
    }
    hd->device.name = new_str(ser->name);
    hd->func = ser->line;
    if(ser->name && !strcmp(ser->name, "AgereModem")) {
      str_printf(&hd->unix_dev_name, 0, "/dev/ttyAGS%u", ser->line);
    }
    else {
      str_printf(&hd->unix_dev_name, 0, "/dev/ttyS%u", ser->line);
    }
    for(i = 0; i < (int) skip_devs; i++) {
      if(!strcmp(skip_dev[i], hd->unix_dev_name)) {
        hd->tag.skip_mouse = hd->tag.skip_modem = hd->tag.skip_braille = 1;
        break;
      }
    }
    if(ser->device) {
      if(strstr(ser->device, "modem-printer")) {
        hd->tag.ser_device = 1;
      }
      else if(strstr(ser->device, "infrared")) {
         hd->tag.ser_device = 2;
      }
      else if(strstr(ser->device, "modem")) {
         hd->tag.ser_device = 3;
      }
    }
    if(ser->baud) {
      res = add_res_entry(&hd->res, new_mem(sizeof *res));
      res->baud.type = res_baud;
      res->baud.speed = ser->baud;
    }
    res = add_res_entry(&hd->res, new_mem(sizeof *res));
    res->io.type = res_io;
    res->io.enabled = 1;
    res->io.base = ser->port;
    res->io.access = acc_rw;

    res = add_res_entry(&hd->res, new_mem(sizeof *res));
    res->irq.type = res_irq;
    res->irq.enabled = 1;
    res->irq.base = ser->irq;

    /* skip Dell Remote Access Cards - bug #145051 */
    for(hd2 = hd_data->hd; hd2; hd2 = hd2->next) {
      if(
        hd2->vendor.id == MAKE_ID(TAG_PCI, 0x1028) && /* Dell */
        hd2->device.id >= MAKE_ID(TAG_PCI, 0x07) &&
        hd2->device.id <= MAKE_ID(TAG_PCI, 0x12) /* range that covers DRACs */
      ) {
        for(res2 = hd2->res; res2; res2 = res2->next) {
          if(
            res2->any.type == res_io &&
            ser->port >= res2->io.base &&
            ser->port < res2->io.base + res2->io.range
          ) {
            hd->tag.skip_mouse = hd->tag.skip_modem = hd->tag.skip_braille = 1;
          }
        }
      }
    }
  }

  for(ser = hd_data->serial; ser; ser = next) {
    next = ser->next;

    free_mem(ser->name);
    free_mem(ser->device);
    free_mem(ser);
  }
  hd_data->serial = NULL;

#if 0
  if(hd_module_is_active(hd_data, "irda")) {
    hd = add_hd_entry(hd_data, __LINE__, 0); 
    hd->base_class.id = bc_comm;
    hd->sub_class.id = sc_com_ser;
    hd->prog_if.id = 0x80;
    hd->device.name = new_str("IrDA Serial");
    hd->unix_dev_name = new_str("/dev/ircomm0");
  }
#endif
}
Пример #22
0
void get_usb_devs(hd_data_t *hd_data)
{
  uint64_t ul0;
  unsigned u1, u2, u3;
  hd_t *hd, *hd1;
  usb_t *usb;
  str_list_t *sl, *usb_devs = NULL;
  char *s, *s1, *t;
  hd_res_t *res;
  size_t l;
  str_list_t *sf_bus, *sf_bus_e;
  char *sf_dev, *sf_dev_2;

  sf_bus = read_dir("/sys/bus/usb/devices", 'l');

  if(!sf_bus) {
    ADD2LOG("sysfs: no such bus: usb\n");
    return;
  }

  for(sf_bus_e = sf_bus; sf_bus_e; sf_bus_e = sf_bus_e->next) {
    sf_dev = hd_read_sysfs_link("/sys/bus/usb/devices", sf_bus_e->str);

    if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev, "bNumInterfaces"), &ul0, 0)) {
      add_str_list(&usb_devs, sf_dev);
      ADD2LOG("  usb dev: %s\n", hd_sysfs_id(sf_dev));
    }
  }

  for(sf_bus_e = sf_bus; sf_bus_e; sf_bus_e = sf_bus_e->next) {
    sf_dev = new_str(hd_read_sysfs_link("/sys/bus/usb/devices", sf_bus_e->str));

    ADD2LOG(
      "  usb device: name = %s\n    path = %s\n",
      sf_bus_e->str,
      hd_sysfs_id(sf_dev)
    );

    if(
      hd_attr_uint(get_sysfs_attr_by_path(sf_dev, "bInterfaceNumber"), &ul0, 16)
    ) {
      hd = add_hd_entry(hd_data, __LINE__, 0);

      hd->detail = new_mem(sizeof *hd->detail);
      hd->detail->type = hd_detail_usb;
      hd->detail->usb.data = usb = new_mem(sizeof *usb);

      hd->sysfs_id = new_str(hd_sysfs_id(sf_dev));
      hd->sysfs_bus_id = new_str(sf_bus_e->str);

      hd->bus.id = bus_usb;
      hd->func = ul0;

      usb->ifdescr = ul0;

      if((s = get_sysfs_attr_by_path(sf_dev, "modalias"))) {
        s = canon_str(s, strlen(s));
        ADD2LOG("    modalias = \"%s\"\n", s);
        if(s && *s) {
          hd->modalias = s;
          s = NULL;
        }
        s = free_mem(s);
      }

      ADD2LOG("    bInterfaceNumber = %u\n", hd->func);

      if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev, "bInterfaceClass"), &ul0, 16)) {
        usb->i_cls = ul0;
        ADD2LOG("    bInterfaceClass = %u\n", usb->i_cls);
      }

      if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev, "bInterfaceSubClass"), &ul0, 16)) {
        usb->i_sub = ul0;
        ADD2LOG("    bInterfaceSubClass = %u\n", usb->i_sub);
      }

      if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev, "bInterfaceProtocol"), &ul0, 16)) {
        usb->i_prot = ul0;
        ADD2LOG("    bInterfaceProtocol = %u\n", usb->i_prot);
      }

      /* device has longest matching sysfs id */
      u2 = strlen(sf_dev);
      s = NULL;
      for(u3 = 0, sl = usb_devs; sl; sl = sl->next) {
        u1 = strlen(sl->str);
        if(u1 > u3 && u1 <= u2 && !strncmp(sf_dev, sl->str, u1)) {
          u3 = u1;
          s = sl->str;
        }
      }

      if(s) {
        ADD2LOG("    if: %s @ %s\n", hd->sysfs_bus_id, hd_sysfs_id(s));
        sf_dev_2 = new_str(s);
        if(sf_dev_2) {

          if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev_2, "bDeviceClass"), &ul0, 16)) {
            usb->d_cls = ul0;
            ADD2LOG("    bDeviceClass = %u\n", usb->d_cls);
          }

          if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev_2, "bDeviceSubClass"), &ul0, 16)) {
            usb->d_sub = ul0;
            ADD2LOG("    bDeviceSubClass = %u\n", usb->d_sub);
          }

          if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev_2, "bDeviceProtocol"), &ul0, 16)) {
            usb->d_prot = ul0;
            ADD2LOG("    bDeviceProtocol = %u\n", usb->d_prot);
          }

          if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev_2, "idVendor"), &ul0, 16)) {
            usb->vendor = ul0;
            ADD2LOG("    idVendor = 0x%04x\n", usb->vendor);
          }

          if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev_2, "idProduct"), &ul0, 16)) {
            usb->device = ul0;
            ADD2LOG("    idProduct = 0x%04x\n", usb->device);
          }

          if((s = get_sysfs_attr_by_path(sf_dev_2, "manufacturer"))) {
            usb->manufact = canon_str(s, strlen(s));
            ADD2LOG("    manufacturer = \"%s\"\n", usb->manufact);
          }

          if((s = get_sysfs_attr_by_path(sf_dev_2, "product"))) {
            usb->product = canon_str(s, strlen(s));
            ADD2LOG("    product = \"%s\"\n", usb->product);
          }

          if((s = get_sysfs_attr_by_path(sf_dev_2, "serial"))) {
            usb->serial = canon_str(s, strlen(s));
            ADD2LOG("    serial = \"%s\"\n", usb->serial);
          }

          if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev_2, "bcdDevice"), &ul0, 16)) {
            usb->rev = ul0;
            ADD2LOG("    bcdDevice = %04x\n", usb->rev);
          }

          if((s = get_sysfs_attr_by_path(sf_dev_2, "speed"))) {
            s = canon_str(s, strlen(s));
            if(!strcmp(s, "1.5")) usb->speed = 15*100000;
            else if(!strcmp(s, "12")) usb->speed = 12*1000000;
            else if(!strcmp(s, "480")) usb->speed = 480*1000000;
            ADD2LOG("    speed = \"%s\"\n", s);
            s = free_mem(s);
          }

          sf_dev_2 = free_mem(sf_dev_2);
        }
      }

      if(usb->vendor || usb->device) {
        hd->vendor.id = MAKE_ID(TAG_USB, usb->vendor);
        hd->device.id = MAKE_ID(TAG_USB, usb->device);
      }

      if(usb->manufact) hd->vendor.name = new_str(usb->manufact);
      if(usb->product) hd->device.name = new_str(usb->product);
      if(usb->serial) hd->serial = new_str(usb->serial);

      if(usb->rev) str_printf(&hd->revision.name, 0, "%x.%02x", usb->rev >> 8, usb->rev & 0xff);

      if(usb->speed) {
        res = add_res_entry(&hd->res, new_mem(sizeof *res));
        res->baud.type = res_baud;
        res->baud.speed = usb->speed;
      }

      s = hd_sysfs_find_driver(hd_data, hd->sysfs_id, 1);
      if(s) add_str_list(&hd->drivers, s);

      set_class_entries(hd_data, hd, usb);

      if(!hd_data->scanner_db) {
        hd_data->scanner_db = hd_module_list(hd_data, 1);
      }

      if(
        hd->drivers &&
        search_str_list(hd_data->scanner_db, hd->drivers->str)
      ) {
        hd->base_class.id = bc_scanner;
      }

      // ###### FIXME
      if(hd->base_class.id == bc_modem) {
        hd->unix_dev_name = new_str("/dev/ttyACM0");
      }
    }

    sf_dev = free_mem(sf_dev);
  }
Пример #23
0
void get_serial_modem(hd_data_t *hd_data)
{
  hd_t *hd;
  int i, j, fd;
  unsigned modem_info, baud;
  char *command;
  ser_device_t *sm;
  int chk_usb = hd_probe_feature(hd_data, pr_modem_usb);

  /* serial modems & usb modems */
  for(hd = hd_data->hd; hd; hd = hd->next) {
    if(
      (
        (
          hd->base_class.id == bc_comm &&
          hd->sub_class.id == sc_com_ser &&
          !hd->tag.ser_skip &&
          hd->tag.ser_device != 2 &&		/* cf. serial.c */
          !has_something_attached(hd_data, hd)
        ) ||
        (
          chk_usb &&
          hd->bus.id == bus_usb &&
          hd->base_class.id == bc_modem
        )
      ) && hd->unix_dev_name
    ) {
      if(dev_name_duplicate(hd_data, hd->unix_dev_name)) continue;
      if((fd = open(hd->unix_dev_name, O_RDWR | O_NONBLOCK)) >= 0) {
        sm = add_ser_modem_entry(&hd_data->ser_modem, new_mem(sizeof *sm));
        sm->dev_name = new_str(hd->unix_dev_name);
        sm->fd = fd;
        sm->hd_idx = hd->idx;
        sm->do_io = 1;
        init_modem(sm);
      }
    }
  }

  if(!hd_data->ser_modem) return;

  PROGRESS(2, 0, "init");

  usleep(300000);		/* PnP protocol; 200ms seems to be too fast  */
  
  for(sm = hd_data->ser_modem; sm; sm = sm->next) {
    modem_info = TIOCM_DTR | TIOCM_RTS;
    ioctl(sm->fd, TIOCMBIS, &modem_info);
    ioctl(sm->fd, TIOCMGET, &modem_info);
    if(!(modem_info & (TIOCM_DSR | TIOCM_CD))) {
      sm->do_io = 0;
    }
  }

  /* just a quick test if we get a response to an AT command */

  for(i = 0; i < 4; i++) {
    PROGRESS(3, i + 1, "at test");

    for(sm = hd_data->ser_modem; sm; sm = sm->next) {
      if(!sm->is_modem)
        set_modem_speed(sm, i == 0 ? 115200 : i == 1 ? 38400 : i == 2 ? 9600 : 1200);
    }

    at_cmd(hd_data, "AT\r", 1, 1);

    for(sm = hd_data->ser_modem; sm; sm = sm->next) {
      if(strstr(sm->buf, "OK") || strstr(sm->buf, "0")) {
        sm->is_modem = 1;
        sm->do_io = 0;
      }
      sm->buf_len = 0;		/* clear buffer */
    }
  }

  for(sm = hd_data->ser_modem; sm; sm = sm->next) {
    if((sm->do_io = sm->is_modem)) {
      sm->max_baud = sm->cur_baud;
    }
  }

  /* check for init string */
  PROGRESS(4, 0, "init string");

  command = NULL;
  for(i = 0; (unsigned) i < MAX_INIT_STRING; i++) {
    str_printf(&command, 0, "AT %s\r", init_strings[i]);
    at_cmd(hd_data, command, 1, 1);

    for(sm = hd_data->ser_modem; sm; sm = sm->next) {
      if(strstr(sm->buf, "OK") || strstr(sm->buf, "0")) {
        str_printf(&sm->init_string2, -1,
          "%s %s", sm->init_string2 ? "" : "AT", init_strings[i]
        );
      }
    }
  }
  command = free_mem(command);

  for(sm = hd_data->ser_modem; sm; sm = sm->next)
    if(sm->is_modem)
      str_printf(&sm->init_string1, -1, "ATZ");

  {
    int cmds[] = { 1, 3, 4, 5, 6 };
    char at[10];
    int i, j, ModemsCount = 0;
    str_list_t **responces = NULL;
    for(sm = hd_data->ser_modem; sm; sm = sm->next)
      if(sm->is_modem)
	ModemsCount++;
    responces = new_mem(ModemsCount * sizeof *responces);
    
    at_cmd(hd_data, "ATI\r", 0, 1);
    for(j = 0, sm = hd_data->ser_modem; sm; sm = sm->next) {
      if(sm->is_modem)
	responces[j++] = str_list_dup(sm->at_resp);
    }

    for(i = 0; (unsigned) i < sizeof cmds / sizeof *cmds; i++) {
      int atx = cmds[i];
      sprintf(at, "ATI%d\r", atx);
      at_cmd(hd_data, at, 0, 1);
      for(j = 0, sm = hd_data->ser_modem; sm; sm = sm->next) {
	if(sm->is_modem) {
	  if(atx == 1 && check_for_responce(responces[j], "Hagenuk", 7) &&
	     (check_for_responce(sm->at_resp, "Speed Dragon", 12) ||
	      check_for_responce(sm->at_resp, "Power Dragon", 12))) {
	    free_mem(sm->init_string1);
	    free_mem(sm->init_string2);
	    sm->init_string1 = new_str("AT&F");
	    sm->init_string2 = new_str("ATB8");
	  }
	  if(atx == 3 && check_for_responce(responces[j], "346900", 6) &&
	     check_for_responce(sm->at_resp, "3Com U.S. Robotics ISDN", 23)) {
	    free_mem(sm->init_string1);
	    free_mem(sm->init_string2);
	    sm->init_string1 = new_str("AT&F");
	    sm->init_string2 = new_str("AT*PPP=1");
	  }
	  if(atx == 4 && check_for_responce(responces[j], "SP ISDN", 7) &&
	     check_for_responce(sm->at_resp, "Sportster ISDN TA", 17)) {
	    free_mem(sm->init_string1);
	    free_mem(sm->init_string2);
	    sm->init_string1 = new_str("AT&F");
	    sm->init_string2 = new_str("ATB3");
	  }
	  if(atx == 6 && check_for_responce(responces[j], "644", 3) &&
	     check_for_responce(sm->at_resp, "ELSA MicroLink ISDN", 19)) {
	    free_mem(sm->init_string1);
	    free_mem(sm->init_string2);
	    sm->init_string1 = new_str("AT&F");
	    sm->init_string2 = new_str("AT$IBP=HDLCP");
	    free_mem(sm->pppd_option);
	    sm->pppd_option = new_str("default-asyncmap");
	  }
	  if(atx == 6 && check_for_responce(responces[j], "643", 3) &&
	     check_for_responce(sm->at_resp, "MicroLink ISDN/TLV.34", 21)) {
	    free_mem(sm->init_string1);
	    free_mem(sm->init_string2);
	    sm->init_string1 = new_str("AT&F");
	    sm->init_string2 = new_str("AT\\N10%P1");
	  }
	  if(atx == 5 && check_for_responce(responces[j], "ISDN TA", 6) &&
	     check_for_responce(sm->at_resp, "ISDN TA;ASU", 4)) {
	    free_mem(sm->vend);
	    sm->vend = new_str("ASUS");
	    free_mem(sm->user_name);
	    sm->user_name = new_str("ISDNLink TA");
	    free_mem(sm->init_string1);
	    free_mem(sm->init_string2);
	    sm->init_string1 = new_str("AT&F");
	    sm->init_string2 = new_str("ATB40");
	  }
	  if(atx==3 && check_for_responce(responces[j], "128000", 6) &&
	     check_for_responce(sm->at_resp, "Lasat Speed", 11)) {
	    free_mem(sm->init_string1);
	    free_mem(sm->init_string2);
	    sm->init_string1 = new_str("AT&F");
	    sm->init_string2 = new_str("AT\\P1&B2X3");
	  }
	  if(atx == 1 &&
	     (check_for_responce(responces[j], "28642", 5) ||
	      check_for_responce(responces[j], "1281", 4) ||
	      check_for_responce(responces[j], "1282", 4) ||
	      check_for_responce(responces[j], "1283", 4) ||
	      check_for_responce(responces[j], "1291", 4) ||
	      check_for_responce(responces[j], "1292", 4) ||
	      check_for_responce(responces[j], "1293", 4)) &&
	     (check_for_responce(sm->at_resp, "Elite 2864I", 11) ||
	      check_for_responce(sm->at_resp, "ZyXEL omni", 10))) {
	    free_mem(sm->init_string1);
	    free_mem(sm->init_string2);
	    sm->init_string1 = new_str("AT&F");
	    sm->init_string2 = new_str("AT&O2B40");
	  }
	  j++;
	}
      }
    }

    for(i = 0; i < ModemsCount; i++) free_str_list(responces[i]);
    free_mem(responces);
  }

  /* now, go for the maximum speed... */
  PROGRESS(5, 0, "speed");

  for(i = MAX_SPEED - 1; i >= 0; i--) {
    baud = speeds[i].baud;
    for(j = 0, sm = hd_data->ser_modem; sm; sm = sm->next) {
      if(sm->is_modem) {
        if(baud > sm->max_baud) {
          sm->do_io = set_modem_speed(sm, baud) ? 0 : 1;
          if(sm->do_io) j++;
        }
      }
    }

    /* no modems */
    if(!j) continue;

    at_cmd(hd_data, "AT\r", 1, 0);

    for(sm = hd_data->ser_modem; sm; sm = sm->next) {
      if(strstr(sm->buf, "OK") || strstr(sm->buf, "0")) {
        sm->max_baud = sm->cur_baud;
      }
      else {
        sm->do_io = 0;
      }
      sm->buf_len = 0;		/* clear buffer */
    }
  }

  /* now, fix it all up... */
  for(sm = hd_data->ser_modem; sm; sm = sm->next) {
    if(sm->is_modem) {
      set_modem_speed(sm, sm->max_baud);
      sm->do_io = 1;
    }
  }

#if 0
  /* just for testing */
  if((hd_data->debug & HD_DEB_MODEM)) {
    int i;
    int cmds[] = { 0, 1, 2, 3, 6 };
    char at[10];

    PROGRESS(8, 0, "testing");

    at_cmd(hd_data, "ATI\r", 0, 1);
    for(i = 0; (unsigned) i < sizeof cmds / sizeof *cmds; i++) {
      sprintf(at, "ATI%d\r", cmds[i]);
      at_cmd(hd_data, at, 0, 1);
    }
    at_cmd(hd_data, "AT\r", 0, 1);
  }
#endif

  PROGRESS(5, 0, "pnp id");

  at_cmd(hd_data, "ATI9\r", 1, 1);

  for(sm = hd_data->ser_modem; sm; sm = sm->next) {
    if(sm->is_modem) {
      chk4id(sm);

      if(!sm->user_name) guess_modem_name(hd_data, sm);
    }

    /* reset serial lines */
    tcflush(sm->fd, TCIOFLUSH);
    tcsetattr(sm->fd, TCSAFLUSH, &sm->tio);
    close(sm->fd);
  }
}