staticint asix_set_sw_mii(struct usbnet *dev, int in_pm)
{ int ret;
ret = asix_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL, in_pm);
if (ret < 0)
netdev_err(dev->net, "Failed to enable software MII access\n"); return ret;
}
staticint asix_set_hw_mii(struct usbnet *dev, int in_pm)
{ int ret;
ret = asix_write_cmd(dev, AX_CMD_SET_HW_MII, 0x0000, 0, 0, NULL, in_pm); if (ret < 0)
netdev_err(dev->net, "Failed to enable hardware MII access\n"); return ret;
}
staticint asix_check_host_enable(struct usbnet *dev, int in_pm)
{ int i, ret;
u8 smsr;
for (i = 0; i < AX_HOST_EN_RETRIES; ++i) {
ret = asix_set_sw_mii(dev, in_pm); if (ret == -ENODEV || ret == -ETIMEDOUT) break;
usleep_range(1000, 1100);
ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG,
0, 0, 1, &smsr, in_pm); if (ret == -ENODEV) break; elseif (ret < 0) continue; elseif (smsr & AX_HOST_EN) break;
}
return i >= AX_HOST_EN_RETRIES ? -ETIMEDOUT : ret;
}
staticvoid reset_asix_rx_fixup_info(struct asix_rx_fixup_info *rx)
{ /* Reset the variables that have a lifetime outside of * asix_rx_fixup_internal() so that future processing starts from a * known set of initial conditions.
*/
if (rx->ax_skb) { /* Discard any incomplete Ethernet frame in the netdev buffer */
kfree_skb(rx->ax_skb);
rx->ax_skb = NULL;
}
/* Assume the Data header 32-bit word is at the start of the current * or next URB socket buffer so reset all the state variables.
*/
rx->remaining = 0;
rx->split_head = false;
rx->header = 0;
}
int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb, struct asix_rx_fixup_info *rx)
{ int offset = 0;
u16 size;
/* When an Ethernet frame spans multiple URB socket buffers, * do a sanity test for the Data header synchronisation. * Attempt to detect the situation of the previous socket buffer having * been truncated or a socket buffer was missing. These situations * cause a discontinuity in the data stream and therefore need to avoid * appending bad data to the end of the current netdev socket buffer. * Also avoid unnecessarily discarding a good current netdev socket * buffer.
*/ if (rx->remaining && (rx->remaining + sizeof(u32) <= skb->len)) {
offset = ((rx->remaining + 1) & 0xfffe);
rx->header = get_unaligned_le32(skb->data + offset);
offset = 0;
size = (u16)(rx->header & 0x7ff); if (size != ((~rx->header >> 16) & 0x7ff)) {
netdev_err(dev->net, "asix_rx_fixup() Data Header synchronisation was lost, remaining %d\n",
rx->remaining);
reset_asix_rx_fixup_info(rx);
}
}
while (offset + sizeof(u16) <= skb->len) {
u16 copy_length;
/* take frame length from Data header 32-bit word */
size = (u16)(rx->header & 0x7ff); if (size != ((~rx->header >> 16) & 0x7ff)) {
netdev_err(dev->net, "asix_rx_fixup() Bad Header Length 0x%x, offset %d\n",
rx->header, offset);
reset_asix_rx_fixup_info(rx); return 0;
} if (size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) {
netdev_dbg(dev->net, "asix_rx_fixup() Bad RX Length %d\n",
size);
reset_asix_rx_fixup_info(rx); return 0;
}
/* Sometimes may fail to get a netdev socket buffer but * continue to process the URB socket buffer so that * synchronisation of the Ethernet frame Data header * word is maintained.
*/
rx->ax_skb = netdev_alloc_skb_ip_align(dev->net, size);
/* We need to push 4 bytes in front of frame (packet_len) * and maybe add 4 bytes after the end (if padlen is 4) * * Avoid skb_copy_expand() expensive call, using following rules : * - We are allowed to push 4 bytes in headroom if skb_header_cloned() * is false (and if we have 4 bytes of headroom) * - We are allowed to put 4 bytes at tail if skb_cloned() * is false (and if we have 4 bytes of tailroom) * * TCP packets for example are cloned, but __skb_header_release() * was called in tcp stack, allowing us to use headroom for our needs.
*/ if (!skb_header_cloned(skb) &&
!(padlen && skb_cloned(skb)) &&
headroom + tailroom >= 4 + padlen) { /* following should not happen, but better be safe */ if (headroom < 4 ||
tailroom < padlen) {
skb->data = memmove(skb->head + 4, skb->data, skb->len);
skb_set_tail_pointer(skb, skb->len);
}
} else { struct sk_buff *skb2;
int asix_mdio_read(struct net_device *netdev, int phy_id, int loc)
{ return __asix_mdio_read(netdev, phy_id, loc, false);
}
staticint __asix_mdio_write(struct net_device *netdev, int phy_id, int loc, int val, bool in_pm)
{ struct usbnet *dev = netdev_priv(netdev);
__le16 res = cpu_to_le16(val); int ret;
/* align data to 16 bit boundaries, read the missing data from
the EEPROM */ if (eeprom->offset & 1) {
ret = asix_read_cmd(dev, AX_CMD_READ_EEPROM, first_word, 0, 2,
&eeprom_buff[0], 0); if (ret < 0) {
netdev_err(net, "Failed to read EEPROM at offset 0x%02x.\n", first_word); goto free;
}
}
if ((eeprom->offset + eeprom->len) & 1) {
ret = asix_read_cmd(dev, AX_CMD_READ_EEPROM, last_word, 0, 2,
&eeprom_buff[last_word - first_word], 0); if (ret < 0) {
netdev_err(net, "Failed to read EEPROM at offset 0x%02x.\n", last_word); goto free;
}
}
/* write data to EEPROM */
ret = asix_write_cmd(dev, AX_CMD_WRITE_ENABLE, 0x0000, 0, 0, NULL, 0); if (ret < 0) {
netdev_err(net, "Failed to enable EEPROM write\n"); goto free;
}
msleep(20);
for (i = first_word; i <= last_word; i++) {
netdev_dbg(net, "write to EEPROM at offset 0x%02x, data 0x%04x\n",
i, eeprom_buff[i - first_word]);
ret = asix_write_cmd(dev, AX_CMD_WRITE_EEPROM, i,
eeprom_buff[i - first_word], 0, NULL, 0); if (ret < 0) {
netdev_err(net, "Failed to write EEPROM at offset 0x%02x.\n",
i); goto free;
}
msleep(20);
}
ret = asix_write_cmd(dev, AX_CMD_WRITE_DISABLE, 0x0000, 0, 0, NULL, 0); if (ret < 0) {
netdev_err(net, "Failed to disable EEPROM write\n"); goto free;
}
if (netif_running(net)) return -EBUSY; if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL;
eth_hw_addr_set(net, addr->sa_data);
/* We use the 20 byte dev->data * for our 6 byte mac buffer * to avoid allocating memory that
* is tricky to free later */
memcpy(data->mac_addr, addr->sa_data, ETH_ALEN);
asix_write_cmd_async(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN,
data->mac_addr);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.