static int gelic_card_set_link_mode(struct gelic_card *card, int mode) { int status; u64 v1, v2; status = lv1_net_control(bus_id(card), dev_id(card), GELIC_LV1_SET_NEGOTIATION_MODE, GELIC_LV1_PHY_ETHERNET_0, mode, 0, &v1, &v2); if (status) { pr_info("%s: failed setting negotiation mode %d\n", __func__, status); return -EBUSY; } card->link_mode = mode; return 0; }
static void gelic_card_get_ether_port_status(struct gelic_card *card, int inform) { u64 v2; struct net_device *ether_netdev; lv1_net_control(bus_id(card), dev_id(card), GELIC_LV1_GET_ETH_PORT_STATUS, GELIC_LV1_VLAN_TX_ETHERNET_0, 0, 0, &card->ether_port_status, &v2); if (inform) { ether_netdev = card->netdev[GELIC_PORT_ETHERNET_0]; if (card->ether_port_status & GELIC_LV1_ETHER_LINK_UP) netif_carrier_on(ether_netdev); else netif_carrier_off(ether_netdev); } }
static u32 gelic_net_get_link(struct net_device *netdev) { struct gelic_net_card *card = netdev_priv(netdev); int status; u64 v1, v2; int link; status = lv1_net_control(bus_id(card), dev_id(card), GELIC_NET_GET_ETH_PORT_STATUS, GELIC_NET_PORT, 0, 0, &v1, &v2); if (status) return 0; /* link down */ if (v1 & GELIC_NET_LINK_UP) link = 1; else link = 0; return link; }
static int gelic_net_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) { struct gelic_net_card *card = netdev_priv(netdev); int status; u64 v1, v2; int speed, duplex; speed = duplex = -1; status = lv1_net_control(bus_id(card), dev_id(card), GELIC_NET_GET_ETH_PORT_STATUS, GELIC_NET_PORT, 0, 0, &v1, &v2); if (status) { /* link down */ } else { if (v1 & GELIC_NET_FULL_DUPLEX) { duplex = DUPLEX_FULL; } else { duplex = DUPLEX_HALF; } if (v1 & GELIC_NET_SPEED_10 ) { speed = SPEED_10; } else if (v1 & GELIC_NET_SPEED_100) { speed = SPEED_100; } else if (v1 & GELIC_NET_SPEED_1000) { speed = SPEED_1000; } } cmd->supported = SUPPORTED_TP | SUPPORTED_Autoneg | SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full; cmd->advertising = cmd->supported; cmd->speed = speed; cmd->duplex = duplex; cmd->autoneg = AUTONEG_ENABLE; /* always enabled */ cmd->port = PORT_TP; return 0; }
/** * gelic_ether_setup_netdev - initialization of net_device * @netdev: net_device structure * @card: card structure * * Returns 0 on success or <0 on failure * * gelic_ether_setup_netdev initializes the net_device structure * and register it. **/ int __devinit gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card) { int status; u64 v1, v2; netdev->features = NETIF_F_IP_CSUM; status = lv1_net_control(bus_id(card), dev_id(card), GELIC_LV1_GET_MAC_ADDRESS, 0, 0, 0, &v1, &v2); v1 <<= 16; if (status || !is_valid_ether_addr((u8 *)&v1)) { dev_info(ctodev(card), "%s:lv1_net_control GET_MAC_ADDR failed %d\n", __func__, status); return -EINVAL; } memcpy(netdev->dev_addr, &v1, ETH_ALEN); if (card->vlan_required) { netdev->hard_header_len += VLAN_HLEN; /* * As vlan is internally used, * we can not receive vlan packets */ netdev->features |= NETIF_F_VLAN_CHALLENGED; } status = register_netdev(netdev); if (status) { dev_err(ctodev(card), "%s:Couldn't register %s %d\n", __func__, netdev->name, status); return status; } dev_info(ctodev(card), "%s: MAC addr %pM\n", netdev->name, netdev->dev_addr); return 0; }
static int gelic_net_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) { int status; struct gelic_card *card; u64 v1, v2; if (ps3_compare_firmware_version(2, 2, 0) < 0 || !capable(CAP_NET_ADMIN)) return -EPERM; if (wol->wolopts & ~WAKE_MAGIC) return -EINVAL; card = netdev_card(netdev); if (wol->wolopts & WAKE_MAGIC) { status = lv1_net_control(bus_id(card), dev_id(card), GELIC_LV1_SET_WOL, GELIC_LV1_WOL_MAGIC_PACKET, 0, GELIC_LV1_WOL_MP_ENABLE, &v1, &v2); if (status) { pr_info("%s: enabling WOL failed %d\n", __func__, status); status = -EIO; goto done; } status = lv1_net_control(bus_id(card), dev_id(card), GELIC_LV1_SET_WOL, GELIC_LV1_WOL_ADD_MATCH_ADDR, 0, GELIC_LV1_WOL_MATCH_ALL, &v1, &v2); if (!status) ps3_sys_manager_set_wol(1); else { pr_info("%s: enabling WOL filter failed %d\n", __func__, status); status = -EIO; } } else { status = lv1_net_control(bus_id(card), dev_id(card), GELIC_LV1_SET_WOL, GELIC_LV1_WOL_MAGIC_PACKET, 0, GELIC_LV1_WOL_MP_DISABLE, &v1, &v2); if (status) { pr_info("%s: disabling WOL failed %d\n", __func__, status); status = -EIO; goto done; } status = lv1_net_control(bus_id(card), dev_id(card), GELIC_LV1_SET_WOL, GELIC_LV1_WOL_DELETE_MATCH_ADDR, 0, GELIC_LV1_WOL_MATCH_ALL, &v1, &v2); if (!status) ps3_sys_manager_set_wol(0); else { pr_info("%s: removing WOL filter failed %d\n", __func__, status); status = -EIO; } } done: return status; }
static void gelic_debug_init(void) { s64 result; u64 v2; u64 mac; u64 vlan_id; result = lv1_open_device(GELIC_BUS_ID, GELIC_DEVICE_ID, 0); if (result) lv1_panic(0); map_dma_mem(GELIC_BUS_ID, GELIC_DEVICE_ID, &dbg, sizeof(dbg), &bus_addr); memset(&dbg, 0, sizeof(dbg)); dbg.descr.buf_addr = bus_addr + offsetof(struct debug_block, pkt); wmb(); result = lv1_net_control(GELIC_BUS_ID, GELIC_DEVICE_ID, GELIC_LV1_GET_MAC_ADDRESS, 0, 0, 0, &mac, &v2); if (result) lv1_panic(0); mac <<= 16; h_eth = (struct ethhdr *)dbg.pkt; memset(&h_eth->dest, 0xff, 6); memcpy(&h_eth->src, &mac, 6); header_size = sizeof(struct ethhdr); result = lv1_net_control(GELIC_BUS_ID, GELIC_DEVICE_ID, GELIC_LV1_GET_VLAN_ID, GELIC_LV1_VLAN_TX_ETHERNET_0, 0, 0, &vlan_id, &v2); if (!result) { h_eth->type = 0x8100; header_size += sizeof(struct vlantag); h_vlan = (struct vlantag *)(h_eth + 1); h_vlan->vlan = vlan_id; h_vlan->subtype = 0x0800; h_ip = (struct iphdr *)(h_vlan + 1); } else { h_eth->type = 0x0800; h_ip = (struct iphdr *)(h_eth + 1); } header_size += sizeof(struct iphdr); h_ip->ver_len = 0x45; h_ip->ttl = 10; h_ip->proto = 0x11; h_ip->src = 0x00000000; h_ip->dest = 0xffffffff; header_size += sizeof(struct udphdr); h_udp = (struct udphdr *)(h_ip + 1); h_udp->src = GELIC_DEBUG_PORT; h_udp->dest = GELIC_DEBUG_PORT; pmsgc = pmsg = (char *)(h_udp + 1); }
/** * gelic_net_setup_netdev - initialization of net_device * @card: card structure * * Returns 0 on success or <0 on failure * * gelic_net_setup_netdev initializes the net_device structure **/ static int gelic_net_setup_netdev(struct gelic_net_card *card) { struct net_device *netdev = card->netdev; struct sockaddr addr; unsigned int i; int status; u64 v1, v2; SET_MODULE_OWNER(netdev); SET_NETDEV_DEV(netdev, &card->dev->core); spin_lock_init(&card->tx_dma_lock); card->rx_csum = GELIC_NET_RX_CSUM_DEFAULT; gelic_net_setup_netdev_ops(netdev); netdev->features = NETIF_F_IP_CSUM; status = lv1_net_control(bus_id(card), dev_id(card), GELIC_NET_GET_MAC_ADDRESS, 0, 0, 0, &v1, &v2); if (status || !is_valid_ether_addr((u8 *)&v1)) { dev_info(ctodev(card), "%s:lv1_net_control GET_MAC_ADDR failed %d\n", __func__, status); return -EINVAL; } v1 <<= 16; memcpy(addr.sa_data, &v1, ETH_ALEN); memcpy(netdev->dev_addr, addr.sa_data, ETH_ALEN); dev_info(ctodev(card), "MAC addr %02x:%02x:%02x:%02x:%02x:%02x\n", netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2], netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]); card->vlan_index = -1; /* no vlan */ for (i = 0; i < GELIC_NET_VLAN_MAX; i++) { status = lv1_net_control(bus_id(card), dev_id(card), GELIC_NET_GET_VLAN_ID, i + 1, /* index; one based */ 0, 0, &v1, &v2); if (status == GELIC_NET_VLAN_NO_ENTRY) { dev_dbg(ctodev(card), "GELIC_VLAN_ID no entry:%d, VLAN disabled\n", status); card->vlan_id[i] = 0; } else if (status) { dev_dbg(ctodev(card), "%s:GELIC_NET_VLAN_ID faild, status=%d\n", __func__, status); card->vlan_id[i] = 0; } else { card->vlan_id[i] = (u32)v1; dev_dbg(ctodev(card), "vlan_id:%d, %lx\n", i, v1); } } if (card->vlan_id[GELIC_NET_VLAN_WIRED - 1]) card->vlan_index = GELIC_NET_VLAN_WIRED - 1; status = register_netdev(netdev); if (status) { dev_err(ctodev(card), "%s:Couldn't register net_device: %d\n", __func__, status); return status; } return 0; }
s64 debug_init(void) { s64 result; u64 v2; result = find_device_by_type(DEV_TYPE_ETH, 0, &bus_id, &dev_id, NULL); if (result) return result; result = map_dma_mem(bus_id, dev_id, dbg, sizeof(struct debug_block), &bus_addr); if (result) return result; memset(dbg, 0, sizeof(struct debug_block)); dbg->descr.buf_addr = bus_addr + offsetof(struct debug_block, pkt); u64 mac; result = lv1_net_control(bus_id, dev_id, GELIC_LV1_GET_MAC_ADDRESS, 0, 0, 0, &mac, &v2); if (result) return result; mac <<= 16; h_eth = (struct ethhdr*)dbg->pkt; memset(&h_eth->dest, 0xff, 6); memcpy(&h_eth->src, &mac, 6); header_size = sizeof(struct ethhdr); u64 vlan_id; result = lv1_net_control(bus_id, dev_id, GELIC_LV1_GET_VLAN_ID, \ GELIC_LV1_VLAN_TX_ETHERNET_0, 0, 0, &vlan_id, &v2); if (result == 0) { h_eth->type = 0x8100; header_size += sizeof(struct vlantag); h_vlan = (struct vlantag*)(h_eth+1); h_vlan->vlan = vlan_id; h_vlan->subtype = 0x0800; h_ip = (struct iphdr*)(h_vlan+1); } else { h_eth->type = 0x0800; h_ip = (struct iphdr*)(h_eth+1); } header_size += sizeof(struct iphdr); h_ip->ver_len = 0x45; h_ip->ttl = 10; h_ip->proto = 0x11; h_ip->src = 0x00000000; h_ip->dest = 0xffffffff; header_size += sizeof(struct udphdr); h_udp = (struct udphdr*)(h_ip+1); h_udp->src = DEBUG_PORT; h_udp->dest = DEBUG_PORT; pmsg = (char*)(h_udp+1); debug_initialized = 1; return 0; }