diff options
author | harti <harti@FreeBSD.org> | 2003-06-13 13:50:38 +0000 |
---|---|---|
committer | harti <harti@FreeBSD.org> | 2003-06-13 13:50:38 +0000 |
commit | 7666b2bd95de2a0754ceffe2e2f13cfe35cceb18 (patch) | |
tree | 53f83572198d124654b3f8506d009b312ef8cc7a /sys/dev/en | |
parent | ab9fef466773acba414e5eac44a2b632a12c68f4 (diff) | |
download | FreeBSD-src-7666b2bd95de2a0754ceffe2e2f13cfe35cceb18.zip FreeBSD-src-7666b2bd95de2a0754ceffe2e2f13cfe35cceb18.tar.gz |
Implement the ioctl that returns a list of currently open VCCs.
Diffstat (limited to 'sys/dev/en')
-rw-r--r-- | sys/dev/en/midway.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/sys/dev/en/midway.c b/sys/dev/en/midway.c index 63cd4bc..86a60c9 100644 --- a/sys/dev/en/midway.c +++ b/sys/dev/en/midway.c @@ -1457,6 +1457,55 @@ en_init(struct en_softc *sc) /* * Ioctls */ +/* + * Return a table of all currently open VCCs. + */ +static struct atmio_vcctable * +en_get_vccs(struct en_softc *sc, int flags) +{ + struct atmio_vcctable *vccs; + struct atmio_vcc *v; + u_int vci, alloc, slot; + + alloc = 10; + vccs = NULL; + do { + vccs = reallocf(vccs, + sizeof(*vccs) + alloc * sizeof(vccs->vccs[0]), + M_TEMP, flags); + if (vccs == NULL) + return (NULL); + + vccs->count = 0; + v = vccs->vccs; + EN_LOCK(sc); + for (vci = 0; vci < MID_N_VC; vci++) { + if ((slot = sc->rxvc2slot[vci]) == RX_NONE || + (sc->rxslot[slot].oth_flags & + (ENOTHER_FREE | ENOTHER_DRAIN)) != 0) + continue; + + if (vccs->count++ == alloc) { + alloc *= 2; + break; + } + bzero(v, sizeof(*v)); + v->flags = ATMIO_FLAG_PVC | sc->rxslot[slot].atm_flags; + v->vpi = 0; + v->vci = vci; + if (sc->rxslot[slot].atm_flags & ATM_PH_AAL5) + v->aal = ATMIO_AAL_5; + else + v->aal = ATMIO_AAL_0; + v->traffic = ATMIO_TRAFFIC_UBR; + v->tparam.pcr = sc->ifatm.mib.pcr; + v++; + } + EN_UNLOCK(sc); + } while (vci < MID_N_VC); + + return (vccs); +} /* * en_ioctl: handle ioctl requests @@ -1476,6 +1525,7 @@ en_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) struct ifaddr *ifa = (struct ifaddr *)data; struct ifreq *ifr = (struct ifreq *)data; struct atm_pseudoioctl *api = (struct atm_pseudoioctl *)data; + struct atmio_vcctable *vtab; int error = 0; switch (cmd) { @@ -1538,6 +1588,26 @@ en_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) error = ifmedia_ioctl(ifp, ifr, &sc->media, cmd); break; + case SIOCATMGETVCCS: /* internal netgraph use */ + vtab = en_get_vccs(sc, M_NOWAIT); + if (vtab == NULL) { + error = ENOMEM; + break; + } + *(void **)data = vtab; + break; + + case SIOCATMGVCCS: /* return vcc table */ + vtab = en_get_vccs(sc, M_WAITOK); + if (vtab == NULL) { + error = ENOMEM; + break; + } + error = copyout(vtab, ifr->ifr_data, sizeof(*vtab) + + vtab->count * sizeof(vtab->vccs[0])); + free(vtab, M_DEVBUF); + break; + default: error = EINVAL; break; |