summaryrefslogtreecommitdiffstats
path: root/sys/dev/en
diff options
context:
space:
mode:
authorharti <harti@FreeBSD.org>2003-06-13 13:50:38 +0000
committerharti <harti@FreeBSD.org>2003-06-13 13:50:38 +0000
commit7666b2bd95de2a0754ceffe2e2f13cfe35cceb18 (patch)
tree53f83572198d124654b3f8506d009b312ef8cc7a /sys/dev/en
parentab9fef466773acba414e5eac44a2b632a12c68f4 (diff)
downloadFreeBSD-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.c70
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;
OpenPOWER on IntegriCloud