⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wrapndis.c

📁 ndis在linux下的无线网卡驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	ndis_key.struct_size = sizeof(ndis_key);	res = miniport_set_info(wnd, OID_802_11_ADD_KEY, &ndis_key,				ndis_key.struct_size);	TRACE2("%08X, %lu", res, (unsigned long)sizeof(ndis_key));	if (res && res != NDIS_STATUS_INVALID_DATA)		EXIT1(return);	res = miniport_query_info(wnd, OID_802_11_ASSOCIATION_INFORMATION,				  &ndis_assoc_info, sizeof(ndis_assoc_info));	TRACE1("%08X", res);	if (res == NDIS_STATUS_NOT_SUPPORTED)		EXIT1(return);	set_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr);	if (mode == Ndis802_11Encryption3Enabled)		set_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr);	/* not all drivers support OID_802_11_CAPABILITY, so we don't	 * know for sure if driver support WPA or WPAPSK; assume	 * WPA */	set_bit(Ndis802_11AuthModeWPA, &wnd->capa.auth);	memset(buf, 0, buf_len);	c = (struct ndis_capability *)buf;	res = miniport_query_info(wnd, OID_802_11_CAPABILITY, buf, buf_len);	if (!(res == NDIS_STATUS_SUCCESS && c->version == 2))		EXIT1(return);	wnd->num_pmkids = c->num_PMKIDs;	for (i = 0; i < c->num_auth_encr_pair; i++) {		struct ndis_auth_encr_pair *ae;		ae = &c->auth_encr_pair[i];		if ((char *)(ae + 1) > buf + buf_len)			break;		switch (ae->auth_mode) {		case Ndis802_11AuthModeOpen:		case Ndis802_11AuthModeShared:		case Ndis802_11AuthModeWPA:		case Ndis802_11AuthModeWPAPSK:		case Ndis802_11AuthModeWPANone:		case Ndis802_11AuthModeWPA2:		case Ndis802_11AuthModeWPA2PSK:			set_bit(ae->auth_mode, &wnd->capa.auth);			break;		default:			WARNING("unknown auth_mode: %d", ae->auth_mode);			break;		}		switch (ae->encr_mode) {		case Ndis802_11EncryptionDisabled:		case Ndis802_11Encryption1Enabled:		case Ndis802_11Encryption2Enabled:		case Ndis802_11Encryption3Enabled:			set_bit(ae->encr_mode, &wnd->capa.encr);			break;		default:			WARNING("unknown encr_mode: %d", ae->encr_mode);			break;		}	}	EXIT1(return);}wstdcall NTSTATUS NdisDispatchDeviceControl(struct device_object *fdo,					    struct irp *irp){	struct wrap_ndis_device *wnd;	TRACE3("fdo: %p", fdo);	/* for now, we don't have anything intresting here, so pass it	 * down to bus driver */	wnd = fdo->reserved;	return IoPassIrpDown(wnd->nmb->pdo, irp);}WIN_FUNC_DECL(NdisDispatchDeviceControl,2)wstdcall NTSTATUS NdisDispatchPower(struct device_object *fdo, struct irp *irp){	struct io_stack_location *irp_sl;	struct wrap_ndis_device *wnd;	enum ndis_power_state state;	NTSTATUS status;	NDIS_STATUS ndis_status;	irp_sl = IoGetCurrentIrpStackLocation(irp);	wnd = fdo->reserved;	IOTRACE("fdo: %p, fn: %d:%d, wnd: %p", fdo, irp_sl->major_fn,		irp_sl->minor_fn, wnd);	if ((irp_sl->params.power.type == SystemPowerState &&	     irp_sl->params.power.state.system_state > PowerSystemWorking) ||	    (irp_sl->params.power.type == DevicePowerState &&	     irp_sl->params.power.state.device_state > PowerDeviceD0))		state = NdisDeviceStateD3;	else		state = NdisDeviceStateD0;	switch (irp_sl->minor_fn) {	case IRP_MN_SET_POWER:		if (state == NdisDeviceStateD0) {			status = IoSyncForwardIrp(wnd->nmb->pdo, irp);			if (status != STATUS_SUCCESS)				break;			ndis_status = miniport_set_power_state(wnd, state);			if (ndis_status != NDIS_STATUS_SUCCESS)				WARNING("couldn't set power to %d: %08X",					state, ndis_status);			TRACE2("%s: device resumed", wnd->net_dev->name);			irp->io_status.status = status = STATUS_SUCCESS;			IoCompleteRequest(irp, IO_NO_INCREMENT);			break;		} else {			ndis_status = miniport_set_power_state(wnd, state);			/* TODO: handle error case */			if (ndis_status != NDIS_STATUS_SUCCESS)				WARNING("setting power to %d failed: %08X",					state, ndis_status);			status = IoAsyncForwardIrp(wnd->nmb->pdo, irp);		}		break;	case IRP_MN_QUERY_POWER:		if (wnd->attributes & NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND) {			ndis_status =				miniport_query_info(wnd, OID_PNP_QUERY_POWER,						    &state, sizeof(state));			TRACE2("%d, %08X", state, ndis_status);			/* this OID must always succeed */			if (ndis_status != NDIS_STATUS_SUCCESS)				TRACE1("query power returns %08X", ndis_status);			irp->io_status.status = STATUS_SUCCESS;		} else			irp->io_status.status = STATUS_SUCCESS;		status = IoPassIrpDown(wnd->nmb->pdo, irp);		break;	case IRP_MN_WAIT_WAKE:	case IRP_MN_POWER_SEQUENCE:		/* TODO: implement WAIT_WAKE */		status = IoPassIrpDown(wnd->nmb->pdo, irp);		break;	default:		status = IoPassIrpDown(wnd->nmb->pdo, irp);		break;	}	IOEXIT(return status);}WIN_FUNC_DECL(NdisDispatchPower,2)wstdcall NTSTATUS NdisDispatchPnp(struct device_object *fdo, struct irp *irp){	struct io_stack_location *irp_sl;	struct wrap_ndis_device *wnd;	struct device_object *pdo;	NTSTATUS status;	IOTRACE("fdo: %p, irp: %p", fdo, irp);	irp_sl = IoGetCurrentIrpStackLocation(irp);	wnd = fdo->reserved;	pdo = wnd->nmb->pdo;	switch (irp_sl->minor_fn) {	case IRP_MN_START_DEVICE:		status = IoSyncForwardIrp(pdo, irp);		if (status != STATUS_SUCCESS)			break;		if (wrap_ndis_start_device(wnd) == NDIS_STATUS_SUCCESS)			status = STATUS_SUCCESS;		else			status = STATUS_FAILURE;		irp->io_status.status = status;		IoCompleteRequest(irp, IO_NO_INCREMENT);		break;	case IRP_MN_QUERY_STOP_DEVICE:		/* TODO: implement in NDIS */		status = IoPassIrpDown(wnd->nmb->pdo, irp);		break;	case IRP_MN_STOP_DEVICE:		miniport_halt(wnd);		irp->io_status.status = STATUS_SUCCESS;		status = IoAsyncForwardIrp(pdo, irp);		break;	case IRP_MN_REMOVE_DEVICE:		TRACE1("%s", wnd->net_dev->name);		miniport_pnp_event(wnd, NdisDevicePnPEventSurpriseRemoved, 0);		if (wrap_ndis_remove_device(wnd)) {			status = STATUS_FAILURE;			break;		}		/* wnd is already freed */		status = IoAsyncForwardIrp(pdo, irp);		IoDetachDevice(fdo);		IoDeleteDevice(fdo);		break;	default:		status = IoAsyncForwardIrp(pdo, irp);		break;	}	IOTRACE("status: %08X", status);	IOEXIT(return status);}WIN_FUNC_DECL(NdisDispatchPnp,2)static void set_task_offload(struct wrap_ndis_device *wnd, void *buf,			     const int buf_size){	struct ndis_task_offload_header *task_offload_header;	struct ndis_task_offload *task_offload;	struct ndis_task_tcp_ip_checksum *csum = NULL;	struct ndis_task_tcp_large_send *tso = NULL;	NDIS_STATUS status;	memset(buf, 0, buf_size);	task_offload_header = buf;	task_offload_header->version = NDIS_TASK_OFFLOAD_VERSION;	task_offload_header->size = sizeof(*task_offload_header);	task_offload_header->encap_format.flags.fixed_header_size = 1;	task_offload_header->encap_format.header_size = sizeof(struct ethhdr);	task_offload_header->encap_format.encap = IEEE_802_3_Encapsulation;	status = miniport_query_info(wnd, OID_TCP_TASK_OFFLOAD, buf, buf_size);	TRACE1("%08X", status);	if (status != NDIS_STATUS_SUCCESS)		EXIT1(return);	if (task_offload_header->offset_first_task == 0)		EXIT1(return);	task_offload = ((void *)task_offload_header +			task_offload_header->offset_first_task);	while (1) {		TRACE1("%d, %d", task_offload->version, task_offload->task);		switch(task_offload->task) {		case TcpIpChecksumNdisTask:			csum = (void *)task_offload->task_buf;			break;		case TcpLargeSendNdisTask:			tso = (void *)task_offload->task_buf;			break;		default:			TRACE1("%d", task_offload->task);			break;		}		if (task_offload->offset_next_task == 0)			break;		task_offload = (void *)task_offload +			task_offload->offset_next_task;	}	if (tso)		TRACE1("%u, %u, %d, %d", tso->max_size, tso->min_seg_count,		       tso->tcp_opts, tso->ip_opts);	if (!csum)		EXIT1(return);	TRACE1("%08x, %08x", csum->v4_tx.value, csum->v4_rx.value);	task_offload_header->encap_format.flags.fixed_header_size = 1;	task_offload_header->encap_format.header_size = sizeof(struct ethhdr);	task_offload_header->offset_first_task = sizeof(*task_offload_header);	task_offload = ((void *)task_offload_header +			task_offload_header->offset_first_task);	task_offload->offset_next_task = 0;	task_offload->size = sizeof(*task_offload);	task_offload->task = TcpIpChecksumNdisTask;	memcpy(task_offload->task_buf, csum, sizeof(*csum));	task_offload->task_buf_length = sizeof(*csum);	status = miniport_set_info(wnd, OID_TCP_TASK_OFFLOAD,				   task_offload_header,				   sizeof(*task_offload_header) +				   sizeof(*task_offload) + sizeof(*csum));	TRACE1("%08X", status);	if (status != NDIS_STATUS_SUCCESS)		EXIT2(return);	wnd->tx_csum = csum->v4_tx;	if (csum->v4_tx.tcp_csum && csum->v4_tx.udp_csum) {		if (csum->v4_tx.ip_csum) {			wnd->net_dev->features |= NETIF_F_HW_CSUM;			TRACE1("hw checksum enabled");		} else {			wnd->net_dev->features |= NETIF_F_IP_CSUM;			TRACE1("IP checksum enabled");		}		if (wnd->sg_dma_size)			wnd->net_dev->features |= NETIF_F_SG;	}	wnd->rx_csum = csum->v4_rx;	EXIT1(return);}static void get_supported_oids(struct wrap_ndis_device *wnd){	NDIS_STATUS res;	int i, n, needed;	ndis_oid *oids;	res = miniport_query_info_needed(wnd, OID_GEN_SUPPORTED_LIST, NULL, 0,					 &needed);	if (!(res == NDIS_STATUS_BUFFER_TOO_SHORT ||	      res == NDIS_STATUS_INVALID_LENGTH))		EXIT1(return);	oids = kmalloc(needed, GFP_KERNEL);	if (!oids) {		TRACE1("couldn't allocate memory");		EXIT1(return);	}	res = miniport_query_info(wnd, OID_GEN_SUPPORTED_LIST, oids, needed);	if (res) {		TRACE1("failed: %08X", res);		kfree(oids);		EXIT1(return);	}	for (i = 0, n = needed / sizeof(*oids); i < n; i++) {		TRACE1("oid: %08X", oids[i]);		/* if a wireless device didn't say so for		 * OID_GEN_PHYSICAL_MEDIUM (they should, but in case) */		if (wnd->physical_medium != NdisPhysicalMediumWirelessLan &&		    oids[i] == OID_802_11_SSID)			wnd->physical_medium = NdisPhysicalMediumWirelessLan;	}	kfree(oids);	EXIT1(return);}#if defined(HAVE_ETHTOOL)static void ndis_get_drvinfo(struct net_device *dev,			     struct ethtool_drvinfo *info){	struct wrap_ndis_device *wnd = netdev_priv(dev);	strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 1);	strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 1);	strncpy(info->fw_version, wnd->wd->driver->version,		sizeof(info->fw_version) - 1);	if (wrap_is_pci_bus(wnd->wd->dev_bus))		strncpy(info->bus_info, pci_name(wnd->wd->pci.pdev),			sizeof(info->bus_info) - 1);#ifdef CONFIG_USB	else		usb_make_path(wnd->wd->usb.udev, info->bus_info,			      sizeof(info->bus_info) - 1);#endif	return;}static u32 ndis_get_link(struct net_device *dev){	struct wrap_ndis_device *wnd = netdev_priv(dev);	return netif_carrier_ok(wnd->net_dev);}static void ndis_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol){	struct wrap_ndis_device *wnd = netdev_priv(dev);	if (wnd->ndis_wolopts & NDIS_PNP_WAKE_UP_MAGIC_PACKET)		wol->wolopts |= WAKE_MAGIC;	/* no other options supported */	return;}static int ndis_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol){	struct wrap_ndis_device *wnd = netdev_priv(dev);	struct ndis_pnp_capabilities pnp_capa;	NDIS_STATUS status;	if (!(wol->wolopts & WAKE_MAGIC))		return -EINVAL;	if (!(wnd->attributes & NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND))		return -EOPNOTSUPP;	status = miniport_query_info(wnd, OID_PNP_CAPABILITIES,				     &pnp_capa, sizeof(pnp_capa));	if (status != NDIS_STATUS_SUCCESS)		return -EOPNOTSUPP;	/* we always suspend to D3 */	TRACE1("%d, %d", pnp_capa.wakeup_capa.min_magic_packet_wakeup,	       pnp_capa.wakeup_capa.min_pattern_wakeup);	if (pnp_capa.wakeup_capa.min_magic_packet_wakeup != NdisDeviceStateD3)		return -EOPNOTSUPP;	/* no other options supported */	wnd->ndis_wolopts = NDIS_PNP_WAKE_UP_MAGIC_PACKET;	return 0;}static u32 ndis_get_tx_csum(struct net_device *dev){	struct wrap_ndis_device *wnd = netdev_priv(dev);	if (wnd->tx_csum.tcp_csum && wnd->tx_csum.udp_csum)		return 1;	else		return 0;}static u32 ndis_get_rx_csum(struct net_device *dev){	struct wrap_ndis_device *wnd = netdev_priv(dev);	if (wnd->rx_csum.value)		return 1;	else		return 0;} static int ndis_set_tx_csum(struct net_device *dev, u32 data){	struct wrap_ndis_device *wnd = netdev_priv(dev);	if (data && (wnd->tx_csum.value == 0))		return -EOPNOTSUPP;	if (wnd->tx_csum.ip_csum) {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)		ethtool_op_set_tx_hw_csum(dev, data);#else		dev->features |= NETIF_F_HW_CSUM;#endif	} else		ethtool_op_set_tx_csum(dev, data);	return 0;}static int ndis_set_rx_csum(struct net_device *dev, u32 data){	struct wrap_ndis_device *wnd = netdev_priv(dev);	if (data && (wnd->tx_csum.value == 0))		return -EOPNOTSUPP;	/* TODO: enable/disable rx csum through NDIS */	return 0;}static u32 ndis_get_sg(struct net_device *dev){	struct wrap_ndis_device *wnd = netdev_priv(dev);	if (wnd->sg_dma_size)		return ethtool_op_get_sg(dev);	else		return 0;} static int ndis_set_sg(struct net_device *dev, u32 data){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -