Skip to content
Snippets Groups Projects
netxen_nic_init.c 30.9 KiB
Newer Older
	netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_UNDERSIZE_FRAME_ERR,
				    &data);

	netxen_nic_pci_change_crbwindow(adapter, 1);
	netxen_nic_clear_stats(adapter);
	return 0;
}

int
netxen_nic_do_ioctl(struct netxen_adapter *adapter, void *u_data,
		    struct netxen_port *port)
{
	struct netxen_nic_ioctl_data data;
	struct netxen_nic_ioctl_data *up_data;
	int retval = 0;
	struct netxen_statistics netxen_stats;

	up_data = (void *)u_data;

	DPRINTK(INFO, "doing ioctl for %p\n", adapter);
	if (copy_from_user(&data, (void __user *)up_data, sizeof(data))) {
		/* evil user tried to crash the kernel */
		DPRINTK(ERR, "bad copy from userland: %d\n", (int)sizeof(data));
		retval = -EFAULT;
		goto error_out;
	}

	/* Shouldn't access beyond legal limits of  "char u[64];" member */
	if (!data.ptr && (data.size > sizeof(data.u))) {
		/* evil user tried to crash the kernel */
		DPRINTK(ERR, "bad size: %d\n", data.size);
		retval = -EFAULT;
		goto error_out;
	}

	switch (data.cmd) {
	case netxen_nic_cmd_pci_read:
		if ((retval = netxen_nic_hw_read_wx(adapter, data.off,
						    &(data.u), data.size)))
			goto error_out;
		if (copy_to_user
		    ((void __user *)&(up_data->u), &(data.u), data.size)) {
			DPRINTK(ERR, "bad copy to userland: %d\n",
				(int)sizeof(data));
			retval = -EFAULT;
			goto error_out;
		}
		data.rv = 0;
		break;

	case netxen_nic_cmd_pci_write:
		data.rv = netxen_nic_hw_write_wx(adapter, data.off, &(data.u),
						 data.size);
		break;

	case netxen_nic_cmd_pci_config_read:
		switch (data.size) {
		case 1:
			data.rv = pci_read_config_byte(adapter->ahw.pdev,
						       data.off,
						       (char *)&(data.u));
			break;
		case 2:
			data.rv = pci_read_config_word(adapter->ahw.pdev,
						       data.off,
						       (short *)&(data.u));
			break;
		case 4:
			data.rv = pci_read_config_dword(adapter->ahw.pdev,
							data.off,
							(u32 *) & (data.u));
			break;
		}
		if (copy_to_user
		    ((void __user *)&(up_data->u), &(data.u), data.size)) {
			DPRINTK(ERR, "bad copy to userland: %d\n",
				(int)sizeof(data));
			retval = -EFAULT;
			goto error_out;
		}
		break;

	case netxen_nic_cmd_pci_config_write:
		switch (data.size) {
		case 1:
			data.rv = pci_write_config_byte(adapter->ahw.pdev,
							data.off,
							*(char *)&(data.u));
			break;
		case 2:
			data.rv = pci_write_config_word(adapter->ahw.pdev,
							data.off,
							*(short *)&(data.u));
			break;
		case 4:
			data.rv = pci_write_config_dword(adapter->ahw.pdev,
							 data.off,
							 *(u32 *) & (data.u));
			break;
		}
		break;

	case netxen_nic_cmd_get_stats:
		data.rv =
		    netxen_nic_fill_statistics(adapter, port, &netxen_stats);
		if (copy_to_user
		    ((void __user *)(up_data->ptr), (void *)&netxen_stats,
		     sizeof(struct netxen_statistics))) {
			DPRINTK(ERR, "bad copy to userland: %d\n",
				(int)sizeof(netxen_stats));
			retval = -EFAULT;
			goto error_out;
		}
		up_data->rv = data.rv;
		break;

	case netxen_nic_cmd_clear_stats:
		data.rv = netxen_nic_clear_statistics(adapter, port);
		up_data->rv = data.rv;
		break;

	case netxen_nic_cmd_get_version:
		if (copy_to_user
		    ((void __user *)&(up_data->u), NETXEN_NIC_LINUX_VERSIONID,
		     sizeof(NETXEN_NIC_LINUX_VERSIONID))) {
			DPRINTK(ERR, "bad copy to userland: %d\n",
				(int)sizeof(data));
			retval = -EFAULT;
			goto error_out;
		}
		break;

	default:
		DPRINTK(INFO, "bad command %d for %p\n", data.cmd, adapter);
		retval = -EOPNOTSUPP;
		goto error_out;
	}
	put_user(data.rv, (u16 __user *) (&(up_data->rv)));
	DPRINTK(INFO, "done ioctl for %p well.\n", adapter);

      error_out:
	return retval;
}