From 08bf79582a281d303842ee11951033d2c532f1f3 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 16 May 2013 15:32:17 +0100 Subject: [PATCH] [netdevice] Add "chip" setting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Suggested-by: Robin Smidsrød Signed-off-by: Michael Brown --- src/net/netdev_settings.c | 157 +++++++++++++++++++++++++++++++------- 1 file changed, 131 insertions(+), 26 deletions(-) diff --git a/src/net/netdev_settings.c b/src/net/netdev_settings.c index 8758e980..8f66c553 100644 --- a/src/net/netdev_settings.c +++ b/src/net/netdev_settings.c @@ -45,6 +45,113 @@ struct setting busid_setting __setting ( SETTING_NETDEV ) = { .description = "Bus ID", .type = &setting_type_hex, }; +struct setting chip_setting __setting ( SETTING_NETDEV ) = { + .name = "chip", + .description = "Chip", + .type = &setting_type_string, +}; + +/** + * Store MAC address setting + * + * @v netdev Network device + * @v data Setting data, or NULL to clear setting + * @v len Length of setting data + * @ret rc Return status code + */ +static int netdev_store_mac ( struct net_device *netdev, + const void *data, size_t len ) { + + if ( len != netdev->ll_protocol->ll_addr_len ) + return -EINVAL; + memcpy ( netdev->ll_addr, data, len ); + return 0; +} + +/** + * Fetch MAC address setting + * + * @v netdev Network device + * @v data Buffer to fill with setting data + * @v len Length of buffer + * @ret len Length of setting data, or negative error + */ +static int netdev_fetch_mac ( struct net_device *netdev, void *data, + size_t len ) { + + if ( len > netdev->ll_protocol->ll_addr_len ) + len = netdev->ll_protocol->ll_addr_len; + memcpy ( data, netdev->ll_addr, len ); + return netdev->ll_protocol->ll_addr_len; +} + +/** + * Fetch bus ID setting + * + * @v netdev Network device + * @v data Buffer to fill with setting data + * @v len Length of buffer + * @ret len Length of setting data, or negative error + */ +static int netdev_fetch_busid ( struct net_device *netdev, void *data, + size_t len ) { + struct device_description *desc = &netdev->dev->desc; + struct dhcp_netdev_desc dhcp_desc; + + dhcp_desc.type = desc->bus_type; + dhcp_desc.vendor = htons ( desc->vendor ); + dhcp_desc.device = htons ( desc->device ); + if ( len > sizeof ( dhcp_desc ) ) + len = sizeof ( dhcp_desc ); + memcpy ( data, &dhcp_desc, len ); + return sizeof ( dhcp_desc ); +} + +/** + * Fetch chip setting + * + * @v netdev Network device + * @v data Buffer to fill with setting data + * @v len Length of buffer + * @ret len Length of setting data, or negative error + */ +static int netdev_fetch_chip ( struct net_device *netdev, void *data, + size_t len ) { + const char *chip = netdev->dev->driver_name; + + strncpy ( data, chip, len ); + return strlen ( chip ); +} + +/** A network device setting operation */ +struct netdev_setting_operation { + /** Setting */ + struct setting *setting; + /** Store setting (or NULL if not supported) + * + * @v netdev Network device + * @v data Setting data, or NULL to clear setting + * @v len Length of setting data + * @ret rc Return status code + */ + int ( * store ) ( struct net_device *netdev, const void *data, + size_t len ); + /** Fetch setting + * + * @v netdev Network device + * @v data Buffer to fill with setting data + * @v len Length of buffer + * @ret len Length of setting data, or negative error + */ + int ( * fetch ) ( struct net_device *netdev, void *data, size_t len ); +}; + +/** Network device settings */ +static struct netdev_setting_operation netdev_setting_operations[] = { + { &mac_setting, netdev_store_mac, netdev_fetch_mac }, + { &busid_setting, NULL, netdev_fetch_busid }, + { &chip_setting, NULL, netdev_fetch_chip }, +}; /** * Store value of network device setting @@ -59,15 +166,21 @@ static int netdev_store ( struct settings *settings, struct setting *setting, const void *data, size_t len ) { struct net_device *netdev = container_of ( settings, struct net_device, settings.settings ); + struct netdev_setting_operation *op; + unsigned int i; - if ( setting_cmp ( setting, &mac_setting ) == 0 ) { - if ( len != netdev->ll_protocol->ll_addr_len ) - return -EINVAL; - memcpy ( netdev->ll_addr, data, len ); - return 0; + /* Handle network device-specific settings */ + for ( i = 0 ; i < ( sizeof ( netdev_setting_operations ) / + sizeof ( netdev_setting_operations[0] ) ) ; i++ ) { + op = &netdev_setting_operations[i]; + if ( setting_cmp ( setting, op->setting ) == 0 ) { + if ( op->store ) { + return op->store ( netdev, data, len ); + } else { + return -ENOTSUP; + } + } } - if ( setting_cmp ( setting, &busid_setting ) == 0 ) - return -ENOTSUP; return generic_settings_store ( settings, setting, data, len ); } @@ -77,31 +190,23 @@ static int netdev_store ( struct settings *settings, struct setting *setting, * * @v settings Settings block * @v setting Setting to fetch - * @v data Setting data, or NULL to clear setting - * @v len Length of setting data - * @ret rc Return status code + * @v data Buffer to fill with setting data + * @v len Length of buffer + * @ret len Length of setting data, or negative error */ static int netdev_fetch ( struct settings *settings, struct setting *setting, void *data, size_t len ) { struct net_device *netdev = container_of ( settings, struct net_device, settings.settings ); - struct device_description *desc = &netdev->dev->desc; - struct dhcp_netdev_desc dhcp_desc; + struct netdev_setting_operation *op; + unsigned int i; - if ( setting_cmp ( setting, &mac_setting ) == 0 ) { - if ( len > netdev->ll_protocol->ll_addr_len ) - len = netdev->ll_protocol->ll_addr_len; - memcpy ( data, netdev->ll_addr, len ); - return netdev->ll_protocol->ll_addr_len; - } - if ( setting_cmp ( setting, &busid_setting ) == 0 ) { - dhcp_desc.type = desc->bus_type; - dhcp_desc.vendor = htons ( desc->vendor ); - dhcp_desc.device = htons ( desc->device ); - if ( len > sizeof ( dhcp_desc ) ) - len = sizeof ( dhcp_desc ); - memcpy ( data, &dhcp_desc, len ); - return sizeof ( dhcp_desc ); + /* Handle network device-specific settings */ + for ( i = 0 ; i < ( sizeof ( netdev_setting_operations ) / + sizeof ( netdev_setting_operations[0] ) ) ; i++ ) { + op = &netdev_setting_operations[i]; + if ( setting_cmp ( setting, op->setting ) == 0 ) + return op->fetch ( netdev, data, len ); } return generic_settings_fetch ( settings, setting, data, len );