/* * Solaris version * Probe a given nexus config space for devices. * * fd is the file descriptor of the nexus. * input_args contains commandline options as specified by the user. */ static int do_probe(nexus_t *nexus, probe_info_t *pinfo) { pcitool_reg_t prg; uint32_t bus; uint8_t dev; uint32_t last_bus = nexus->last_bus; uint8_t last_dev = PCI_REG_DEV_M >> PCI_REG_DEV_SHIFT; uint8_t first_bus = nexus->first_bus; uint8_t first_dev = 0; int rval = 0; prg.barnum = 0; /* Config space. */ /* Must read in 4-byte quantities. */ prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_4 + NATIVE_ENDIAN; prg.data = 0; /* * Loop through all valid bus / dev / func combinations to check for * all devices, with the following exceptions: * * When nothing is found at function 0 of a bus / dev combination, skip * the other functions of that bus / dev combination. * * When a found device's function 0 is probed and it is determined that * it is not a multifunction device, skip probing of that device's * other functions. */ for (bus = first_bus; ((bus <= last_bus) && (rval == 0)); bus++) { prg.bus_no = (uint8_t)bus; for (dev = first_dev; ((dev <= last_dev) && (rval == 0)); dev++) { prg.dev_no = dev; rval = probe_dev(nexus, &prg, pinfo); } /* * Ultra-45 southbridge workaround: * ECANCELED tells to skip to the next bus. */ if (rval == ECANCELED) { rval = 0; } } return (rval); }
static void *_monitor_thread(void *arg) { int fd = open_udp_listenfd(VIRTUAL_SWITCH_BOX_LISTEN_PORT); fd_set rset; int ret; struct timeval tv; struct sockaddr_in mc_addr, dev_addr; socklen_t mc_len = sizeof(mc_addr); socklen_t dev_len = sizeof(dev_addr); uint8_t sbuf[16], rbuf[16]; int cmd_len; set_broadcast(fd, true); get_broadcast_address(fd, &mc_addr.sin_addr); mc_addr.sin_family = AF_INET; mc_addr.sin_port = htons(VIRTUAL_SWITCH_LISTEN_PORT); while (1) { FD_ZERO(&rset); FD_SET(fd, &rset); tv.tv_sec = 2; tv.tv_usec = 0; ret = select(fd+1, &rset, NULL, NULL, &tv); if (ret < 0) continue; if (0 == ret) { /* timeout, send keep alive */ _remove_timeout_dev(); memset(sbuf, 0, sizeof(sbuf)); cmd_len = 4; SET_CMD_FIELD(sbuf, 0, uint16_t, VS_CMD_KEEP_ALIVE); SET_CMD_FIELD(sbuf, 2, uint16_t, cmd_len); sendto(fd, sbuf, cmd_len, 0, (struct sockaddr *)&mc_addr, mc_len); continue; } cmd_len = 16; /* get message */ dev_len = sizeof(struct sockaddr_in); ret = recvfrom(fd, rbuf, cmd_len, 0, (struct sockaddr *)&dev_addr, &dev_len); if (ret < 4) continue; uint16_t cmd = GET_CMD_FIELD(rbuf, 0, uint16_t); uint16_t len = GET_CMD_FIELD(rbuf, 2, uint16_t); if (len != ret) { hsb_debug("error cmd: %d, %d\n", len, ret); continue; } //hsb_debug("get a cmd: %x\n", cmd); VS_DEV_T *pdev = _find_dev_by_ip(&dev_addr.sin_addr); if (!pdev) { probe_dev(virtual_switch_drv.id); continue; } switch (cmd) { case VS_CMD_KEEP_ALIVE: { break; } case VS_CMD_STATUS_CHANGED: { uint16_t id = GET_CMD_FIELD(rbuf, 4, uint16_t); uint16_t val = GET_CMD_FIELD(rbuf, 6, uint16_t); _status_updated(pdev->id, id, val); break; } case VS_CMD_EVENT: { uint16_t id = GET_CMD_FIELD(rbuf, 4, uint16_t); uint16_t param = GET_CMD_FIELD(rbuf, 6, uint16_t); uint32_t param2 = GET_CMD_FIELD(rbuf, 8, uint32_t); _event(pdev->id, id, param, param2); break; } default: break; } _refresh_device(pdev); } return NULL; }