📄 i2o_lan.c
字号:
struct i2o_controller *iop = i2o_dev->controller; struct dev_mc_list *mc; u32 msg[10 + 2 * dev->mc_count]; u8 *work8 = (u8 *)(msg + 10); msg[0] = I2O_MESSAGE_SIZE(10 + 2 * dev->mc_count) | SGL_OFFSET_5; msg[1] = I2O_CMD_UTIL_PARAMS_SET << 24 | HOST_TID << 12 | i2o_dev->lct_data.tid; msg[2] = priv->unit << 16 | lan_context; // InitiatorContext msg[3] = 0x0002 << 16 | (u16)-1; // TransactionContext msg[4] = 0; // OperationFlags msg[5] = 0xCC000000 | (16 + 8 * dev->mc_count); // Immediate data SGL msg[6] = 2; // OperationCount msg[7] = 0x0002 << 16 | I2O_PARAMS_TABLE_CLEAR; // Group, Operation msg[8] = 0x0002 << 16 | I2O_PARAMS_ROW_ADD; // Group, Operation msg[9] = dev->mc_count << 16 | (u16)-1; // RowCount, FieldCount for (mc = dev->mc_list; mc ; mc = mc->next, work8 += 8) { memset(work8, 0, 8); memcpy(work8, mc->dmi_addr, mc->dmi_addrlen); // Values } return i2o_post_this(iop, msg, sizeof(msg));}/* * i2o_lan_set_multicast_list(): Enable a network device to receive packets * not send to the protocol address. */static void i2o_lan_set_multicast_list(struct net_device *dev){ struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; u32 filter_mask; if (dev->flags & IFF_PROMISC) { filter_mask = 0x00000002; dprintk(KERN_INFO "%s: Enabling promiscuous mode...\n", dev->name); } else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > priv->max_size_mc_table) { filter_mask = 0x00000004; dprintk(KERN_INFO "%s: Enabling all multicast mode...\n", dev->name); } else if (dev->mc_count) { filter_mask = 0x00000000; dprintk(KERN_INFO "%s: Enabling multicast mode...\n", dev->name); if (i2o_lan_set_mc_table(dev) < 0) printk(KERN_WARNING "%s: Unable to send MAC table.\n", dev->name); } else { filter_mask = 0x00000300; // Broadcast, Multicast disabled dprintk(KERN_INFO "%s: Enabling unicast mode...\n", dev->name); } /* Finally copy new FilterMask to DDM */ if (i2o_lan_set_mc_filter(dev, filter_mask) < 0) printk(KERN_WARNING "%s: Unable to send MAC FilterMask.\n", dev->name);}/* * i2o_lan_change_mtu(): Change maximum transfer unit size. */static int i2o_lan_change_mtu(struct net_device *dev, int new_mtu){ struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; struct i2o_device *i2o_dev = priv->i2o_dev; u32 max_pkt_size; if (i2o_query_scalar(i2o_dev->controller, i2o_dev->lct_data.tid, 0x0000, 6, &max_pkt_size, 4) < 0) return -EFAULT; if (new_mtu < 68 || new_mtu > 9000 || new_mtu > max_pkt_size) return -EINVAL; dev->mtu = new_mtu; i2o_lan_suspend(dev); // to SUSPENDED state, return buckets while (priv->i2o_fbl_tail >= 0) // free buffered buckets dev_kfree_skb(priv->i2o_fbl[priv->i2o_fbl_tail--]); i2o_lan_reset(dev); // to OPERATIONAL state i2o_set_ddm_parameters(dev); // reset some parameters i2o_lan_receive_post(dev); // post new buckets (new size) return 0;}/* Functions to initialize I2O LAN OSM:======================================*//* * i2o_lan_register_device(): Register LAN class device to kernel. */struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev){ struct net_device *dev = NULL; struct i2o_lan_local *priv = NULL; u8 hw_addr[8]; u32 tx_max_out = 0; unsigned short (*type_trans)(struct sk_buff *, struct net_device *); void (*unregister_dev)(struct net_device *dev); switch (i2o_dev->lct_data.sub_class) { case I2O_LAN_ETHERNET: dev = init_etherdev(NULL, sizeof(struct i2o_lan_local)); if (dev == NULL) return NULL; type_trans = eth_type_trans; unregister_dev = unregister_netdev; break;#ifdef CONFIG_ANYLAN case I2O_LAN_100VG: printk(KERN_ERR "i2o_lan: 100base VG not yet supported.\n"); return NULL; break;#endif#ifdef CONFIG_TR case I2O_LAN_TR: dev = init_trdev(NULL, sizeof(struct i2o_lan_local)); if (dev==NULL) return NULL; type_trans = tr_type_trans; unregister_dev = unregister_trdev; break;#endif#ifdef CONFIG_FDDI case I2O_LAN_FDDI: { int size = sizeof(struct net_device) + sizeof(struct i2o_lan_local); dev = (struct net_device *) kmalloc(size, GFP_KERNEL); if (dev == NULL) return NULL; memset((char *)dev, 0, size); dev->priv = (void *)(dev + 1); if (dev_alloc_name(dev, "fddi%d") < 0) { printk(KERN_WARNING "i2o_lan: Too many FDDI devices.\n"); kfree(dev); return NULL; } type_trans = fddi_type_trans; unregister_dev = (void *)unregister_netdevice; fddi_setup(dev); register_netdev(dev); } break;#endif#ifdef CONFIG_NET_FC case I2O_LAN_FIBRE_CHANNEL: dev = init_fcdev(NULL, sizeof(struct i2o_lan_local)); if (dev == NULL) return NULL; type_trans = NULL;/* FIXME: Move fc_type_trans() from drivers/net/fc/iph5526.c to net/802/fc.c * and export it in include/linux/fcdevice.h * type_trans = fc_type_trans; */ unregister_dev = (void *)unregister_fcdev; break;#endif case I2O_LAN_UNKNOWN: default: printk(KERN_ERR "i2o_lan: LAN type 0x%04x not supported.\n", i2o_dev->lct_data.sub_class); return NULL; } priv = (struct i2o_lan_local *)dev->priv; priv->i2o_dev = i2o_dev; priv->type_trans = type_trans; priv->sgl_max = (i2o_dev->controller->status_block->inbound_frame_size - 4) / 3; atomic_set(&priv->buckets_out, 0); /* Set default values for user configurable parameters */ /* Private values are changed via /proc file system */ priv->max_buckets_out = max_buckets_out; priv->bucket_thresh = bucket_thresh; priv->rx_copybreak = rx_copybreak; priv->tx_batch_mode = tx_batch_mode & 0x03; priv->i2o_event_mask = i2o_event_mask; priv->tx_lock = SPIN_LOCK_UNLOCKED; priv->fbl_lock = SPIN_LOCK_UNLOCKED; unit++; i2o_landevs[unit] = dev; priv->unit = unit; if (i2o_query_scalar(i2o_dev->controller, i2o_dev->lct_data.tid, 0x0001, 0, &hw_addr, sizeof(hw_addr)) < 0) { printk(KERN_ERR "%s: Unable to query hardware address.\n", dev->name); unit--; unregister_dev(dev); kfree(dev); return NULL; } dprintk(KERN_DEBUG "%s: hwaddr = %02X:%02X:%02X:%02X:%02X:%02X\n", dev->name, hw_addr[0], hw_addr[1], hw_addr[2], hw_addr[3], hw_addr[4], hw_addr[5]); dev->addr_len = 6; memcpy(dev->dev_addr, hw_addr, 6); if (i2o_query_scalar(i2o_dev->controller, i2o_dev->lct_data.tid, 0x0007, 2, &tx_max_out, sizeof(tx_max_out)) < 0) { printk(KERN_ERR "%s: Unable to query max TX queue.\n", dev->name); unit--; unregister_dev(dev); kfree(dev); return NULL; } dprintk(KERN_INFO "%s: Max TX Outstanding = %d.\n", dev->name, tx_max_out); priv->tx_max_out = tx_max_out; atomic_set(&priv->tx_out, 0); priv->tx_count = 0; INIT_LIST_HEAD(&priv->i2o_batch_send_task.list); priv->i2o_batch_send_task.sync = 0; priv->i2o_batch_send_task.routine = (void *)i2o_lan_batch_send; priv->i2o_batch_send_task.data = (void *)dev; dev->open = i2o_lan_open; dev->stop = i2o_lan_close; dev->get_stats = i2o_lan_get_stats; dev->set_multicast_list = i2o_lan_set_multicast_list; dev->tx_timeout = i2o_lan_tx_timeout; dev->watchdog_timeo = I2O_LAN_TX_TIMEOUT;#ifdef CONFIG_NET_FC if (i2o_dev->lct_data.sub_class == I2O_LAN_FIBRE_CHANNEL) dev->hard_start_xmit = i2o_lan_sdu_send; else#endif dev->hard_start_xmit = i2o_lan_packet_send; if (i2o_dev->lct_data.sub_class == I2O_LAN_ETHERNET) dev->change_mtu = i2o_lan_change_mtu; return dev;}#ifdef MODULE#define i2o_lan_init init_module#endifint __init i2o_lan_init(void){ struct net_device *dev; int i; printk(KERN_INFO "I2O LAN OSM (C) 1999 University of Helsinki.\n"); /* Module params are used as global defaults for private values */ if (max_buckets_out > I2O_LAN_MAX_BUCKETS_OUT) max_buckets_out = I2O_LAN_MAX_BUCKETS_OUT; if (bucket_thresh > max_buckets_out) bucket_thresh = max_buckets_out; /* Install handlers for incoming replies */ if (i2o_install_handler(&i2o_lan_send_handler) < 0) { printk(KERN_ERR "i2o_lan: Unable to register I2O LAN OSM.\n"); return -EINVAL; } lan_send_context = i2o_lan_send_handler.context; if (i2o_install_handler(&i2o_lan_receive_handler) < 0) { printk(KERN_ERR "i2o_lan: Unable to register I2O LAN OSM.\n"); return -EINVAL; } lan_receive_context = i2o_lan_receive_handler.context; if (i2o_install_handler(&i2o_lan_handler) < 0) { printk(KERN_ERR "i2o_lan: Unable to register I2O LAN OSM.\n"); return -EINVAL; } lan_context = i2o_lan_handler.context; for(i=0; i <= MAX_LAN_CARDS; i++) i2o_landevs[i] = NULL; for (i=0; i < MAX_I2O_CONTROLLERS; i++) { struct i2o_controller *iop = i2o_find_controller(i); struct i2o_device *i2o_dev; if (iop==NULL) continue; for (i2o_dev=iop->devices;i2o_dev != NULL;i2o_dev=i2o_dev->next) { if (i2o_dev->lct_data.class_id != I2O_CLASS_LAN) continue; /* Make sure device not already claimed by an ISM */ if (i2o_dev->lct_data.user_tid != 0xFFF) continue; if (unit == MAX_LAN_CARDS) { i2o_unlock_controller(iop); printk(KERN_WARNING "i2o_lan: Too many I2O LAN devices.\n"); return -EINVAL; } dev = i2o_lan_register_device(i2o_dev); if (dev == NULL) { printk(KERN_ERR "i2o_lan: Unable to register I2O LAN device 0x%04x.\n", i2o_dev->lct_data.sub_class); continue; } printk(KERN_INFO "%s: I2O LAN device registered, " "subclass = 0x%04x, unit = %d, tid = %d.\n", dev->name, i2o_dev->lct_data.sub_class, ((struct i2o_lan_local *)dev->priv)->unit, i2o_dev->lct_data.tid); } i2o_unlock_controller(iop); } dprintk(KERN_INFO "%d I2O LAN devices found and registered.\n", unit+1); return 0;}#ifdef MODULEvoid cleanup_module(void){ int i; for (i = 0; i <= unit; i++) { struct net_device *dev = i2o_landevs[i]; struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; struct i2o_device *i2o_dev = priv->i2o_dev; switch (i2o_dev->lct_data.sub_class) { case I2O_LAN_ETHERNET: unregister_netdev(dev); break;#ifdef CONFIG_FDDI case I2O_LAN_FDDI: unregister_netdevice(dev); break;#endif#ifdef CONFIG_TR case I2O_LAN_TR: unregister_trdev(dev); break;#endif#ifdef CONFIG_NET_FC case I2O_LAN_FIBRE_CHANNEL: unregister_fcdev(dev); break;#endif default: printk(KERN_WARNING "%s: Spurious I2O LAN subclass 0x%08x.\n", dev->name, i2o_dev->lct_data.sub_class); } dprintk(KERN_INFO "%s: I2O LAN device unregistered.\n", dev->name); kfree(dev); } i2o_remove_handler(&i2o_lan_handler); i2o_remove_handler(&i2o_lan_send_handler); i2o_remove_handler(&i2o_lan_receive_handler);}EXPORT_NO_SYMBOLS;MODULE_AUTHOR("University of Helsinki, Department of Computer Science");MODULE_DESCRIPTION("I2O Lan OSM");MODULE_LICENSE("GPL");MODULE_PARM(max_buckets_out, "1-" __MODULE_STRING(I2O_LAN_MAX_BUCKETS_OUT) "i");MODULE_PARM_DESC(max_buckets_out, "Total number of buckets to post (1-)");MODULE_PARM(bucket_thresh, "1-" __MODULE_STRING(I2O_LAN_MAX_BUCKETS_OUT) "i");MODULE_PARM_DESC(bucket_thresh, "Bucket post threshold (1-)");MODULE_PARM(rx_copybreak, "1-" "i");MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy only small frames (1-)");MODULE_PARM(tx_batch_mode, "0-2" "i");MODULE_PARM_DESC(tx_batch_mode, "0=Send immediatelly, 1=Send in batches, 2=Switch automatically");#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -