コード例 #1
0
ファイル: if_hatm_ioctl.c プロジェクト: JabirTech/Source
/*
 * IOCTL handler
 */
int
hatm_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
	struct ifreq *ifr = (struct ifreq *)data;
	struct ifaddr *ifa = (struct ifaddr *)data;
	struct hatm_softc *sc = ifp->if_softc;
	struct atmio_vcctable *vtab;
	int error = 0;

	switch (cmd) {

	  case SIOCSIFADDR:
		mtx_lock(&sc->mtx);
		ifp->if_flags |= IFF_UP;
		if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
			hatm_initialize(sc);
		switch (ifa->ifa_addr->sa_family) {

#ifdef INET
		  case AF_INET:
		  case AF_INET6:
			ifa->ifa_rtrequest = atm_rtrequest;
			break;
#endif
		  default:
			break;
		}
		mtx_unlock(&sc->mtx);
		break;

	  case SIOCSIFFLAGS:
		mtx_lock(&sc->mtx);
		if (ifp->if_flags & IFF_UP) {
			if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
				hatm_initialize(sc);
			}
		} else {
			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
				hatm_stop(sc);
			}
		}
		mtx_unlock(&sc->mtx);
		break;

	  case SIOCGIFMEDIA:
	  case SIOCSIFMEDIA:
		error = ifmedia_ioctl(ifp, ifr, &sc->media, cmd);
		break;

	case SIOCSIFMTU:
		/*
		 * Set the interface MTU.
		 */
		if (ifr->ifr_mtu > ATMMTU)
			error = EINVAL;
		else
			ifp->if_mtu = ifr->ifr_mtu;
		break;

	  case SIOCATMGVCCS:
		/* return vcc table */
		vtab = atm_getvccs((struct atmio_vcc **)sc->vccs,
		    HE_MAX_VCCS, sc->open_vccs, &sc->mtx, 1);
		error = copyout(vtab, ifr->ifr_data, sizeof(*vtab) +
		    vtab->count * sizeof(vtab->vccs[0]));
		free(vtab, M_DEVBUF);
		break;

	  case SIOCATMGETVCCS:	/* netgraph internal use */
		vtab = atm_getvccs((struct atmio_vcc **)sc->vccs,
		    HE_MAX_VCCS, sc->open_vccs, &sc->mtx, 0);
		if (vtab == NULL) {
			error = ENOMEM;
			break;
		}
		*(void **)data = vtab;
		break;

	  case SIOCATMOPENVCC:		/* kernel internal use */
		error = hatm_open_vcc(sc, (struct atmio_openvcc *)data);
		break;

	  case SIOCATMCLOSEVCC:		/* kernel internal use */
		error = hatm_close_vcc(sc, (struct atmio_closevcc *)data);
		break;

	  default:
		DBG(sc, IOCTL, ("cmd=%08lx arg=%p", cmd, data));
		error = EINVAL;
		break;
	}

	return (error);
}
コード例 #2
0
int
patm_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
	struct ifreq *ifr = (struct ifreq *)data;
	struct ifaddr *ifa = (struct ifaddr *)data;
	struct patm_softc *sc = ifp->if_softc;
	int error = 0;
	uint32_t cfg;
	struct atmio_vcctable *vtab;

	switch (cmd) {

	  case SIOCSIFADDR:
		mtx_lock(&sc->mtx);
		ifp->if_flags |= IFF_UP;
		if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
			patm_initialize(sc);
		switch (ifa->ifa_addr->sa_family) {

#ifdef INET
		  case AF_INET:
		  case AF_INET6:
			ifa->ifa_rtrequest = atm_rtrequest;
			break;
#endif
		  default:
			break;
		}
		mtx_unlock(&sc->mtx);
		break;

	  case SIOCSIFFLAGS:
		mtx_lock(&sc->mtx);
		if (ifp->if_flags & IFF_UP) {
			if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
				patm_initialize(sc);
			}
		} else {
			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
				patm_stop(sc);
			}
		}
		mtx_unlock(&sc->mtx);
		break;

	  case SIOCGIFMEDIA:
	  case SIOCSIFMEDIA:
		error = ifmedia_ioctl(ifp, ifr, &sc->media, cmd);

		/*
		 * We need to toggle unassigned/idle cells ourself because
		 * the 77252 generates null cells for spacing. When switching
		 * null cells of it gets the timing wrong.
		 */
		mtx_lock(&sc->mtx);
		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
			if (sc->utopia.state & UTP_ST_UNASS) {
				if (!(sc->flags & PATM_UNASS)) {
					cfg = patm_nor_read(sc, IDT_NOR_CFG);
					cfg &= ~IDT_CFG_IDLECLP;
					patm_nor_write(sc, IDT_NOR_CFG, cfg);
					sc->flags |= PATM_UNASS;
				}
			} else {
				if (sc->flags & PATM_UNASS) {
					cfg = patm_nor_read(sc, IDT_NOR_CFG);
					cfg |= IDT_CFG_IDLECLP;
					patm_nor_write(sc, IDT_NOR_CFG, cfg);
					sc->flags &= ~PATM_UNASS;
				}
			}
		} else {
			if (sc->utopia.state & UTP_ST_UNASS)
				sc->flags |= PATM_UNASS;
			else
				sc->flags &= ~PATM_UNASS;
		}
		mtx_unlock(&sc->mtx);
		break;

	  case SIOCSIFMTU:
		/*
		 * Set the interface MTU.
		 */
		if (ifr->ifr_mtu > ATMMTU)
			error = EINVAL;
		else
			ifp->if_mtu = ifr->ifr_mtu;
		break;

	  case SIOCATMOPENVCC:		/* kernel internal use */
		error = patm_open_vcc(sc, (struct atmio_openvcc *)data);
		break;

	  case SIOCATMCLOSEVCC:		/* kernel internal use */
		error = patm_close_vcc(sc, (struct atmio_closevcc *)data);
		break;

	  case SIOCATMGVCCS:	/* external use */
#ifdef CPU_CHERI
#error Unvalidatable ifr_data use.  Unsafe with CheriABI.
#endif
		/* return vcc table */
		vtab = atm_getvccs((struct atmio_vcc **)sc->vccs,
		    sc->mmap->max_conn, sc->vccs_open, &sc->mtx, 1);
		error = copyout(vtab, ifr->ifr_data, sizeof(*vtab) +
		    vtab->count * sizeof(vtab->vccs[0]));
		free(vtab, M_DEVBUF);
		break;

	  case SIOCATMGETVCCS:	/* netgraph internal use */
		vtab = atm_getvccs((struct atmio_vcc **)sc->vccs,
		    sc->mmap->max_conn, sc->vccs_open, &sc->mtx, 0);
		if (vtab == NULL) {
			error = ENOMEM;
			break;
		}
		*(void **)data = vtab;
		break;

	  default:
		patm_debug(sc, IOCTL, "unknown cmd=%08lx arg=%p", cmd, data);
		error = EINVAL;
		break;
	}

	return (error);
}