static int dlpi_get_ifmib(struct dlpi_driver_data *dlpi, int ppa, mib_ifEntry *mib) { dl_get_statistics_req_t stats_req; dl_get_statistics_ack_t *stats_ack; int len; /* first attach to PPA */ if (!dlpi_attach(dlpi, ppa)) return 0; /* grab stats */ stats_req.dl_primitive = DL_GET_STATISTICS_REQ; if (!dlpi_req(dlpi, &stats_req, sizeof(dl_get_statistics_req_t), DL_GET_STATISTICS_ACK, (void **) &stats_ack, &len)) return 0; if (len < sizeof(dl_get_statistics_ack_t) || stats_ack->dl_stat_offset < 0 || stats_ack->dl_stat_offset + sizeof(mib_ifEntry) > len) { ifstat_error("dlpi: invalid data returned by stats ack"); } memcpy(mib, (char *) stats_ack + stats_ack->dl_stat_offset, sizeof(mib_ifEntry)); return 1; }
static int dlpi_map_ifs(struct dlpi_driver_data *dlpi, int (*mapf)(mib_ifEntry *mib, int ppa, char *name, void *mdata), void *mdata) { dl_hp_ppa_req_t ppa_req; dl_hp_ppa_ack_t *ppa_ack; dl_hp_ppa_info_t *ppa_info; mib_ifEntry mib; void *buf; int len, i, ofs; char ifname[sizeof(ppa_info->dl_module_id_1) + 12]; if (!dlpi_attach(dlpi, DLPI_NO_PPA)) return 0; ppa_req.dl_primitive = DL_HP_PPA_REQ; if (!dlpi_req(dlpi, &ppa_req, sizeof(ppa_req), DL_HP_PPA_ACK, (void **) &ppa_ack, &len)) return 0; if (len < sizeof(dl_hp_ppa_ack_t)) { ifstat_error("dlpi: short read for ppa ack"); return 0; } /* copy buffer since used by later calls */ if ((buf = malloc(len)) == NULL) { perror("malloc"); return 0; } memcpy(buf, (void *) ppa_ack, len); ppa_ack = buf; /* browse interface list */ ofs = ppa_ack->dl_offset; for(i = 0; i < ppa_ack->dl_count; i++) { if (ofs < 0 || ofs + sizeof(dl_hp_ppa_info_t) > len) { ifstat_error("dlpi: data returned by ppa ack exceeds data buffer"); free(buf); return 0; } ppa_info = (dl_hp_ppa_info_t *) ((char *) ppa_ack + ofs); if (dlpi_get_ifmib(dlpi, ppa_info->dl_ppa, &mib)) { sprintf(ifname, "%s%d", ppa_info->dl_module_id_1, ppa_info->dl_instance_num); if (!mapf(&mib, ppa_info->dl_ppa, ifname, mdata)) { free(buf); return 0; } } ofs = ppa_ack->dl_offset + ppa_info->dl_next_offset; } free(buf); return 1; }
int main(int argc, char **argv) { char cnambuf[MAXPATHLEN]; struct scc_mode sm; struct strioctl sioc; int fd, speed; char *arg, *cp; char loopchange = 0; char echochange = 0; char clockchange = 0; char *devstr = "/dev/"; int devstrlen; ulong_t ppa; if (argc == 1) { usage(); exit(1); } argc--; argv++; devstrlen = strlen(devstr); if (strncmp(devstr, argv[0], devstrlen) != 0) { if (snprintf(cnambuf, sizeof (cnambuf), "%s%s", devstr, argv[0]) >= sizeof (cnambuf)) { (void) fprintf(stderr, "syncinit: invalid device name (too long) %s\n", argv[0]); exit(1); } } cp = cnambuf; while (*cp) /* find the end of the name */ cp++; cp--; if (!isdigit(*cp)) { (void) fprintf(stderr, "syncinit: %s missing minor device number\n", argv[0]); exit(1); } while (isdigit(*(cp - 1))) cp--; ppa = strtoul(cp, NULL, 10); *cp = '\0'; /* drop number, leaving name of clone device. */ fd = open(cnambuf, O_RDWR|O_EXCL, 0); if (fd < 0) { perror("syncinit: open"); exit(1); } if (dlpi_attach(fd, MAXWAIT, ppa) != 0) { perror("syncinit: dlpi_attach"); exit(1); } (void) printf("device: %s ppa: %d\n", cnambuf, (int)ppa); argc--; argv++; if (argc) { /* setting things */ sioc.ic_cmd = S_IOCGETMODE; sioc.ic_timout = -1; sioc.ic_len = sizeof (struct scc_mode); sioc.ic_dp = (char *)&sm; if (ioctl(fd, I_STR, &sioc) < 0) { perror("S_IOCGETMODE"); (void) fprintf(stderr, "syncinit: can't get sync mode info for %s\n", cnambuf); exit(1); } while (argc-- > 0) { arg = *argv++; if (sscanf(arg, "%d", &speed) == 1) sm.sm_baudrate = speed; else if (strchr(arg, '=')) { if (prefix(arg, "loop")) { if (lookup(yesno, arg)) sm.sm_config |= CONN_LPBK; else sm.sm_config &= ~CONN_LPBK; loopchange++; } else if (prefix(arg, "echo")) { if (lookup(yesno, arg)) sm.sm_config |= CONN_ECHO; else sm.sm_config &= ~CONN_ECHO; echochange++; } else if (prefix(arg, "nrzi")) { if (lookup(yesno, arg)) sm.sm_config |= CONN_NRZI; else sm.sm_config &= ~CONN_NRZI; } else if (prefix(arg, "txc")) { sm.sm_txclock = lookup(txnames, arg); clockchange++; } else if (prefix(arg, "rxc")) { sm.sm_rxclock = lookup(rxnames, arg); clockchange++; } else if (prefix(arg, "speed")) { arg = strchr(arg, '=') + 1; if (sscanf(arg, "%d", &speed) == 1) { sm.sm_baudrate = speed; } else (void) fprintf(stderr, "syncinit: %s %s\n", "bad speed:", arg); } } else if (equal(arg, "external")) { sm.sm_txclock = TXC_IS_TXC; sm.sm_rxclock = RXC_IS_RXC; sm.sm_config &= ~CONN_LPBK; } else if (equal(arg, "sender")) { sm.sm_txclock = TXC_IS_BAUD; sm.sm_rxclock = RXC_IS_RXC; sm.sm_config &= ~CONN_LPBK; } else if (equal(arg, "internal")) { sm.sm_txclock = TXC_IS_PLL; sm.sm_rxclock = RXC_IS_PLL; sm.sm_config &= ~CONN_LPBK; } else if (equal(arg, "stop")) { sm.sm_baudrate = 0; } else (void) fprintf(stderr, "Bad arg: %s\n", arg); } /* * If we're going to change the state of loopback, and we * don't have our own plans for clock sources, use defaults. */ if (loopchange && !clockchange) { if (sm.sm_config & CONN_LPBK) { sm.sm_txclock = TXC_IS_BAUD; sm.sm_rxclock = RXC_IS_BAUD; } else { sm.sm_txclock = TXC_IS_TXC; sm.sm_rxclock = RXC_IS_RXC; } } sioc.ic_cmd = S_IOCSETMODE; sioc.ic_timout = -1; sioc.ic_len = sizeof (struct scc_mode); sioc.ic_dp = (char *)&sm; if (ioctl(fd, I_STR, &sioc) < 0) { perror("S_IOCSETMODE"); (void) ioctl(fd, S_IOCGETMODE, &sm); (void) fprintf(stderr, "syncinit: ioctl failure code = %x\n", sm.sm_retval); exit(1); } } /* Report State */ sioc.ic_cmd = S_IOCGETMODE; sioc.ic_timout = -1; sioc.ic_len = sizeof (struct scc_mode); sioc.ic_dp = (char *)&sm; if (ioctl(fd, I_STR, &sioc) < 0) { perror("S_IOCGETMODE"); (void) fprintf(stderr, "syncinit: can't get sync mode info for %s\n", cnambuf); exit(1); } (void) printf( "speed=%d, loopback=%s, echo=%s, nrzi=%s, txc=%s, rxc=%s\n", sm.sm_baudrate, yesno[((int)(sm.sm_config & CONN_LPBK) > 0)], yesno[((int)(sm.sm_config & CONN_ECHO) > 0)], yesno[((int)(sm.sm_config & CONN_NRZI) > 0)], txnames[sm.sm_txclock], rxnames[sm.sm_rxclock]); return (0); }