FreeBSD/sys/dev/bxe/bxe.c
/*
 * Handles any IOCTL calls from the operating system.
 *
 * Returns:
 *   0 = Success, >0 Failure
 */
Handles any IOCTL calls from the operating system.
Returns:
0 = Success, >0 Failure
Handles any IOCTL calls from the operating system . Returns : 0 = Success > 0 Failure
static int
bxe_ioctl(if_t ifp,
          u_long       command,
          caddr_t      data)
{
    struct bxe_softc *sc = if_getsoftc(ifp);
    struct ifreq *ifr = (struct ifreq *)data;
    int mask = 0;
    int reinit = 0;
    int error = 0;
    int mtu_min = (ETH_MIN_PACKET_SIZE - ETH_HLEN);
    int mtu_max = (MJUM9BYTES - ETH_OVERHEAD - IP_HEADER_ALIGNMENT_PADDING);
    switch (command)
    {
    case SIOCSIFMTU:
        BLOGD(sc, DBG_IOCTL, "Received SIOCSIFMTU ioctl (mtu=%d)\n",
              ifr->ifr_mtu);
        if (sc->mtu == ifr->ifr_mtu) {
            break;
        }
        if ((ifr->ifr_mtu < mtu_min) || (ifr->ifr_mtu > mtu_max)) {
            BLOGE(sc, "Unsupported MTU size %d (range is %d-%d)\n",
                  ifr->ifr_mtu, mtu_min, mtu_max);
            error = EINVAL;
            break;
        }
        atomic_store_rel_int((volatile unsigned int *)&sc->mtu,
                             (unsigned long)ifr->ifr_mtu);
	if_setmtu(ifp, ifr->ifr_mtu);
        reinit = 1;
        break;
    case SIOCSIFFLAGS:
        BLOGD(sc, DBG_IOCTL, "Received SIOCSIFFLAGS ioctl\n");
	BXE_CORE_LOCK(sc);
        if (if_getflags(ifp) & IFF_UP) {
            if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
                bxe_set_rx_mode(sc);
            } else if(sc->state != BXE_STATE_DISABLED) {
		bxe_init_locked(sc);
            }
        } else {
            if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
		bxe_periodic_stop(sc);
		bxe_stop_locked(sc);
            }
        }
	BXE_CORE_UNLOCK(sc);
        break;
    case SIOCADDMULTI:
    case SIOCDELMULTI:
        BLOGD(sc, DBG_IOCTL, "Received SIOCADDMULTI/SIOCDELMULTI ioctl\n");
        if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
	    BXE_CORE_LOCK(sc);
            bxe_set_rx_mode(sc);
	    BXE_CORE_UNLOCK(sc); 
        }
        break;
    case SIOCSIFCAP:
        mask = (ifr->ifr_reqcap ^ if_getcapenable(ifp));
        BLOGD(sc, DBG_IOCTL, "Received SIOCSIFCAP ioctl (mask=0x%08x)\n",
              mask);
        if (mask & IFCAP_LRO) {
	    if_togglecapenable(ifp, IFCAP_LRO);
            BLOGD(sc, DBG_IOCTL, "Turning LRO %s\n",
                  (if_getcapenable(ifp) & IFCAP_LRO) ? "ON" : "OFF");
            reinit = 1;
        }
        if (mask & IFCAP_TXCSUM) {
	    if_togglecapenable(ifp, IFCAP_TXCSUM);
            BLOGD(sc, DBG_IOCTL, "Turning TXCSUM %s\n",
                  (if_getcapenable(ifp) & IFCAP_TXCSUM) ? "ON" : "OFF");
            if (if_getcapenable(ifp) & IFCAP_TXCSUM) {
                if_sethwassistbits(ifp, (CSUM_IP      | 
                                    CSUM_TCP      |
                                    CSUM_UDP      |
                                    CSUM_TSO      |
                                    CSUM_TCP_IPV6 |
                                    CSUM_UDP_IPV6), 0);
            } else {
		if_clearhwassist(ifp); 
            }
        }
        if (mask & IFCAP_RXCSUM) {
	    if_togglecapenable(ifp, IFCAP_RXCSUM);
            BLOGD(sc, DBG_IOCTL, "Turning RXCSUM %s\n",
                  (if_getcapenable(ifp) & IFCAP_RXCSUM) ? "ON" : "OFF");
            if (if_getcapenable(ifp) & IFCAP_RXCSUM) {
                if_sethwassistbits(ifp, (CSUM_IP      |
                                    CSUM_TCP      |
                                    CSUM_UDP      |
                                    CSUM_TSO      |
                                    CSUM_TCP_IPV6 |
                                    CSUM_UDP_IPV6), 0);
            } else {
		if_clearhwassist(ifp); 
            }
        }
        if (mask & IFCAP_TSO4) {
            if_togglecapenable(ifp, IFCAP_TSO4);
            BLOGD(sc, DBG_IOCTL, "Turning TSO4 %s\n",
                  (if_getcapenable(ifp) & IFCAP_TSO4) ? "ON" : "OFF");
        }
        if (mask & IFCAP_TSO6) {
	    if_togglecapenable(ifp, IFCAP_TSO6);
            BLOGD(sc, DBG_IOCTL, "Turning TSO6 %s\n",
                  (if_getcapenable(ifp) & IFCAP_TSO6) ? "ON" : "OFF");
        }
        if (mask & IFCAP_VLAN_HWTSO) {
	    if_togglecapenable(ifp, IFCAP_VLAN_HWTSO);
            BLOGD(sc, DBG_IOCTL, "Turning VLAN_HWTSO %s\n",
                  (if_getcapenable(ifp) & IFCAP_VLAN_HWTSO) ? "ON" : "OFF");
        }
        if (mask & IFCAP_VLAN_HWCSUM) {
            BLOGE(sc, "Changing VLAN_HWCSUM is not supported!\n");
            error = EINVAL;
        }
        if (mask & IFCAP_VLAN_MTU) {
            BLOGE(sc, "Changing VLAN_MTU is not supported!\n");
            error = EINVAL;
        }
        if (mask & IFCAP_VLAN_HWTAGGING) {
            BLOGE(sc, "Changing VLAN_HWTAGGING is not supported!\n");
            error = EINVAL;
        }
        if (mask & IFCAP_VLAN_HWFILTER) {
            BLOGE(sc, "Changing VLAN_HWFILTER is not supported!\n");
            error = EINVAL;
        }
        break;
    case SIOCSIFMEDIA:
    case SIOCGIFMEDIA:
        BLOGD(sc, DBG_IOCTL,
              "Received SIOCSIFMEDIA/SIOCGIFMEDIA ioctl (cmd=%lu)\n",
              (command & 0xff));
        error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
        break;
    default:
        BLOGD(sc, DBG_IOCTL, "Received Unknown Ioctl (cmd=%lu)\n",
              (command & 0xff));
        error = ether_ioctl(ifp, command, data);
        break;
    }
    if (reinit && (if_getdrvflags(sc->ifp) & IFF_DRV_RUNNING)) {
        BLOGD(sc, DBG_LOAD | DBG_IOCTL,
              "Re-initializing hardware from IOCTL change\n");
	bxe_periodic_stop(sc);
	BXE_CORE_LOCK(sc);
	bxe_stop_locked(sc);
	bxe_init_locked(sc);
	BXE_CORE_UNLOCK(sc);
    }
    return (error);
}
static int bxe_ioctl ( if_t ifp , u_long command , caddr_t data ) { struct bxe_softc * sc = if_getsoftc ( ifp ) ; struct ifreq * ifr = ( struct ifreq * ) data ; int mask = 0 ; int reinit = 0 ; int error = 0 ; int mtu_min = ( ETH_MIN_PACKET_SIZE - ETH_HLEN ) ; int mtu_max = ( MJUM9BYTES - ETH_OVERHEAD - IP_HEADER_ALIGNMENT_PADDING ) ; switch ( command ) { case SIOCSIFMTU : BLOGD ( sc , DBG_IOCTL , " \n " , ifr -> ifr_mtu ) ; if ( sc -> mtu == ifr -> ifr_mtu ) { break ; } if ( ( ifr -> ifr_mtu < mtu_min ) || ( ifr -> ifr_mtu > mtu_max ) ) { BLOGE ( sc , " \n " , ifr -> ifr_mtu , mtu_min , mtu_max ) ; error = EINVAL ; break ; } atomic_store_rel_int ( ( volatile unsigned int * ) & sc -> mtu , ( unsigned long ) ifr -> ifr_mtu ) ; if_setmtu ( ifp , ifr -> ifr_mtu ) ; reinit = 1 ; break ; case SIOCSIFFLAGS : BLOGD ( sc , DBG_IOCTL , " \n " ) ; BXE_CORE_LOCK ( sc ) ; if ( if_getflags ( ifp ) & IFF_UP ) { if ( if_getdrvflags ( ifp ) & IFF_DRV_RUNNING ) { bxe_set_rx_mode ( sc ) ; } else if ( sc -> state != BXE_STATE_DISABLED ) { bxe_init_locked ( sc ) ; } } else { if ( if_getdrvflags ( ifp ) & IFF_DRV_RUNNING ) { bxe_periodic_stop ( sc ) ; bxe_stop_locked ( sc ) ; } } BXE_CORE_UNLOCK ( sc ) ; break ; case SIOCADDMULTI : case SIOCDELMULTI : BLOGD ( sc , DBG_IOCTL , " \n " ) ; if ( if_getdrvflags ( ifp ) & IFF_DRV_RUNNING ) { BXE_CORE_LOCK ( sc ) ; bxe_set_rx_mode ( sc ) ; BXE_CORE_UNLOCK ( sc ) ; } break ; case SIOCSIFCAP : mask = ( ifr -> ifr_reqcap ^ if_getcapenable ( ifp ) ) ; BLOGD ( sc , DBG_IOCTL , " \n " , mask ) ; if ( mask & IFCAP_LRO ) { if_togglecapenable ( ifp , IFCAP_LRO ) ; BLOGD ( sc , DBG_IOCTL , " \n " , ( if_getcapenable ( ifp ) & IFCAP_LRO ) ? " " : " " ) ; reinit = 1 ; } if ( mask & IFCAP_TXCSUM ) { if_togglecapenable ( ifp , IFCAP_TXCSUM ) ; BLOGD ( sc , DBG_IOCTL , " \n " , ( if_getcapenable ( ifp ) & IFCAP_TXCSUM ) ? " " : " " ) ; if ( if_getcapenable ( ifp ) & IFCAP_TXCSUM ) { if_sethwassistbits ( ifp , ( CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_TSO | CSUM_TCP_IPV6 | CSUM_UDP_IPV6 ) , 0 ) ; } else { if_clearhwassist ( ifp ) ; } } if ( mask & IFCAP_RXCSUM ) { if_togglecapenable ( ifp , IFCAP_RXCSUM ) ; BLOGD ( sc , DBG_IOCTL , " \n " , ( if_getcapenable ( ifp ) & IFCAP_RXCSUM ) ? " " : " " ) ; if ( if_getcapenable ( ifp ) & IFCAP_RXCSUM ) { if_sethwassistbits ( ifp , ( CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_TSO | CSUM_TCP_IPV6 | CSUM_UDP_IPV6 ) , 0 ) ; } else { if_clearhwassist ( ifp ) ; } } if ( mask & IFCAP_TSO4 ) { if_togglecapenable ( ifp , IFCAP_TSO4 ) ; BLOGD ( sc , DBG_IOCTL , " \n " , ( if_getcapenable ( ifp ) & IFCAP_TSO4 ) ? " " : " " ) ; } if ( mask & IFCAP_TSO6 ) { if_togglecapenable ( ifp , IFCAP_TSO6 ) ; BLOGD ( sc , DBG_IOCTL , " \n " , ( if_getcapenable ( ifp ) & IFCAP_TSO6 ) ? " " : " " ) ; } if ( mask & IFCAP_VLAN_HWTSO ) { if_togglecapenable ( ifp , IFCAP_VLAN_HWTSO ) ; BLOGD ( sc , DBG_IOCTL , " \n " , ( if_getcapenable ( ifp ) & IFCAP_VLAN_HWTSO ) ? " " : " " ) ; } if ( mask & IFCAP_VLAN_HWCSUM ) { BLOGE ( sc , " \n " ) ; error = EINVAL ; } if ( mask & IFCAP_VLAN_MTU ) { BLOGE ( sc , " \n " ) ; error = EINVAL ; } if ( mask & IFCAP_VLAN_HWTAGGING ) { BLOGE ( sc , " \n " ) ; error = EINVAL ; } if ( mask & IFCAP_VLAN_HWFILTER ) { BLOGE ( sc , " \n " ) ; error = EINVAL ; } break ; case SIOCSIFMEDIA : case SIOCGIFMEDIA : BLOGD ( sc , DBG_IOCTL , " \n " , ( command & 0xff ) ) ; error = ifmedia_ioctl ( ifp , ifr , & sc -> ifmedia , command ) ; break ; default : BLOGD ( sc , DBG_IOCTL , " \n " , ( command & 0xff ) ) ; error = ether_ioctl ( ifp , command , data ) ; break ; } if ( reinit && ( if_getdrvflags ( sc -> ifp ) & IFF_DRV_RUNNING ) ) { BLOGD ( sc , DBG_LOAD | DBG_IOCTL , " \n " ) ; bxe_periodic_stop ( sc ) ; BXE_CORE_LOCK ( sc ) ; bxe_stop_locked ( sc ) ; bxe_init_locked ( sc ) ; BXE_CORE_UNLOCK ( sc ) ; } return ( error ) ; }
Handles any IOCTL calls from the operating system.
Handles any IOCTL calls from the operating system .
/* nothing to change */ /* 
        atomic_store_rel_long((volatile unsigned long *)&if_getmtu(ifp),
                              (unsigned long)ifr->ifr_mtu);
	XXX - Not sure why it needs to be atomic
	*/ /* toggle the interface state up or down */ /* check if the interface is up */ /* set the receive mode flags */ /* add/delete multicast addresses */ /* check if the interface is up */ /* set the receive mode flags */ /* find out which capabilities have changed */ /* toggle the LRO capabilites enable flag */ /* toggle the TXCSUM checksum capabilites enable flag */ /* XXX */ /* toggle the RXCSUM checksum capabilities enable flag */ /* XXX */ /* toggle TSO4 capabilities enabled flag */ /* toggle TSO6 capabilities enabled flag */ /* toggle VLAN_HWTSO capabilities enabled flag */ /* toggle VLAN_HWCSUM capabilities enabled flag */ /* XXX investigate this... */ /* toggle VLAN_MTU capabilities enable flag */ /* XXX investigate this... */ /* toggle VLAN_HWTAGGING capabilities enabled flag */ /* XXX investigate this... */ /* toggle VLAN_HWFILTER capabilities enabled flag */ /* XXX investigate this... */ /* XXX not yet...
         * IFCAP_WOL_MAGIC
         */ /* set/get interface media */