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

📄 ueagle-atm.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
 * Stop the modem : kill kernel thread and free data */static void uea_stop(struct uea_softc *sc){	int ret;	uea_enters(INS_TO_USBDEV(sc));	ret = kthread_stop(sc->kthread);	uea_dbg(INS_TO_USBDEV(sc), "kthread finish with status %d\n", ret);	/* stop any pending boot process */	flush_scheduled_work();	uea_request(sc, UEA_SET_MODE, UEA_LOOPBACK_ON, 0, NULL);	usb_kill_urb(sc->urb_int);	kfree(sc->urb_int->transfer_buffer);	usb_free_urb(sc->urb_int);	if (sc->dsp_firm)		release_firmware(sc->dsp_firm);	uea_leaves(INS_TO_USBDEV(sc));}/* syfs interface */static struct uea_softc *dev_to_uea(struct device *dev){	struct usb_interface *intf;	struct usbatm_data *usbatm;	intf = to_usb_interface(dev);	if (!intf)		return NULL;	usbatm = usb_get_intfdata(intf);	if (!usbatm)		return NULL;	return usbatm->driver_data;}static ssize_t read_status(struct device *dev, struct device_attribute *attr,		char *buf){	int ret = -ENODEV;	struct uea_softc *sc;	mutex_lock(&uea_mutex);	sc = dev_to_uea(dev);	if (!sc)		goto out;	ret = snprintf(buf, 10, "%08x\n", sc->stats.phy.state);out:	mutex_unlock(&uea_mutex);	return ret;}static ssize_t reboot(struct device *dev, struct device_attribute *attr,		const char *buf, size_t count){	int ret = -ENODEV;	struct uea_softc *sc;	mutex_lock(&uea_mutex);	sc = dev_to_uea(dev);	if (!sc)		goto out;	sc->reset = 1;	ret = count;out:	mutex_unlock(&uea_mutex);	return ret;}static DEVICE_ATTR(stat_status, S_IWUGO | S_IRUGO, read_status, reboot);static ssize_t read_human_status(struct device *dev, struct device_attribute *attr,		char *buf){	int ret = -ENODEV;	struct uea_softc *sc;	mutex_lock(&uea_mutex);	sc = dev_to_uea(dev);	if (!sc)		goto out;	switch (GET_STATUS(sc->stats.phy.state)) {	case 0:		ret = sprintf(buf, "Modem is booting\n");		break;	case 1:		ret = sprintf(buf, "Modem is initializing\n");		break;	case 2:		ret = sprintf(buf, "Modem is operational\n");		break;	default:		ret = sprintf(buf, "Modem synchronization failed\n");		break;	}out:	mutex_unlock(&uea_mutex);	return ret;}static DEVICE_ATTR(stat_human_status, S_IWUGO | S_IRUGO, read_human_status, NULL);static ssize_t read_delin(struct device *dev, struct device_attribute *attr,		char *buf){	int ret = -ENODEV;	struct uea_softc *sc;	mutex_lock(&uea_mutex);	sc = dev_to_uea(dev);	if (!sc)		goto out;	if (sc->stats.phy.flags & 0x0C00)		ret = sprintf(buf, "ERROR\n");	else if (sc->stats.phy.flags & 0x0030)		ret = sprintf(buf, "LOSS\n");	else		ret = sprintf(buf, "GOOD\n");out:	mutex_unlock(&uea_mutex);	return ret;}static DEVICE_ATTR(stat_delin, S_IWUGO | S_IRUGO, read_delin, NULL);#define UEA_ATTR(name, reset) 					\								\static ssize_t read_##name(struct device *dev, 			\		struct device_attribute *attr, char *buf)	\{ 								\	int ret = -ENODEV; 					\	struct uea_softc *sc; 					\ 								\	mutex_lock(&uea_mutex); 				\	sc = dev_to_uea(dev);					\	if (!sc) 						\		goto out; 					\	ret = snprintf(buf, 10, "%08x\n", sc->stats.phy.name);	\	if (reset)						\		sc->stats.phy.name = 0;				\out: 								\	mutex_unlock(&uea_mutex); 				\	return ret; 						\} 								\								\static DEVICE_ATTR(stat_##name, S_IRUGO, read_##name, NULL)UEA_ATTR(mflags, 1);UEA_ATTR(vidcpe, 0);UEA_ATTR(usrate, 0);UEA_ATTR(dsrate, 0);UEA_ATTR(usattenuation, 0);UEA_ATTR(dsattenuation, 0);UEA_ATTR(usmargin, 0);UEA_ATTR(dsmargin, 0);UEA_ATTR(txflow, 0);UEA_ATTR(rxflow, 0);UEA_ATTR(uscorr, 0);UEA_ATTR(dscorr, 0);UEA_ATTR(usunc, 0);UEA_ATTR(dsunc, 0);/* Retrieve the device End System Identifier (MAC) */#define htoi(x) (isdigit(x) ? x-'0' : toupper(x)-'A'+10)static int uea_getesi(struct uea_softc *sc, u_char * esi){	unsigned char mac_str[2 * ETH_ALEN + 1];	int i;	if (usb_string	    (sc->usb_dev, sc->usb_dev->descriptor.iSerialNumber, mac_str,	     sizeof(mac_str)) != 2 * ETH_ALEN)		return 1;	for (i = 0; i < ETH_ALEN; i++)		esi[i] = htoi(mac_str[2 * i]) * 16 + htoi(mac_str[2 * i + 1]);	return 0;}/* ATM stuff */static int uea_atm_open(struct usbatm_data *usbatm, struct atm_dev *atm_dev){	struct uea_softc *sc = usbatm->driver_data;	return uea_getesi(sc, atm_dev->esi);}static int uea_heavy(struct usbatm_data *usbatm, struct usb_interface *intf){	struct uea_softc *sc = usbatm->driver_data;	wait_event(sc->sync_q, IS_OPERATIONAL(sc));	return 0;}static int claim_interface(struct usb_device *usb_dev,			   struct usbatm_data *usbatm, int ifnum){	int ret;	struct usb_interface *intf = usb_ifnum_to_if(usb_dev, ifnum);	if (!intf) {		uea_err(usb_dev, "interface %d not found\n", ifnum);		return -ENODEV;	}	ret = usb_driver_claim_interface(&uea_driver, intf, usbatm);	if (ret != 0)		uea_err(usb_dev, "can't claim interface %d, error %d\n", ifnum,		       ret);	return ret;}static void create_fs_entries(struct uea_softc *sc, struct usb_interface *intf){	/* sysfs interface */	device_create_file(&intf->dev, &dev_attr_stat_status);	device_create_file(&intf->dev, &dev_attr_stat_mflags);	device_create_file(&intf->dev, &dev_attr_stat_human_status);	device_create_file(&intf->dev, &dev_attr_stat_delin);	device_create_file(&intf->dev, &dev_attr_stat_vidcpe);	device_create_file(&intf->dev, &dev_attr_stat_usrate);	device_create_file(&intf->dev, &dev_attr_stat_dsrate);	device_create_file(&intf->dev, &dev_attr_stat_usattenuation);	device_create_file(&intf->dev, &dev_attr_stat_dsattenuation);	device_create_file(&intf->dev, &dev_attr_stat_usmargin);	device_create_file(&intf->dev, &dev_attr_stat_dsmargin);	device_create_file(&intf->dev, &dev_attr_stat_txflow);	device_create_file(&intf->dev, &dev_attr_stat_rxflow);	device_create_file(&intf->dev, &dev_attr_stat_uscorr);	device_create_file(&intf->dev, &dev_attr_stat_dscorr);	device_create_file(&intf->dev, &dev_attr_stat_usunc);	device_create_file(&intf->dev, &dev_attr_stat_dsunc);}static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,		   const struct usb_device_id *id){	struct usb_device *usb = interface_to_usbdev(intf);	struct uea_softc *sc;	int ret, ifnum = intf->altsetting->desc.bInterfaceNumber;	uea_enters(usb);	/* interface 0 is for firmware/monitoring */	if (ifnum != UEA_INTR_IFACE_NO)		return -ENODEV;	usbatm->flags = (sync_wait[modem_index] ? 0 : UDSL_SKIP_HEAVY_INIT);	/* interface 1 is for outbound traffic */	ret = claim_interface(usb, usbatm, UEA_US_IFACE_NO);	if (ret < 0)		return ret;	/* ADI930 has only 2 interfaces and inbound traffic is on interface 1 */	if (UEA_CHIP_VERSION(id) != ADI930) {		/* interface 2 is for inbound traffic */		ret = claim_interface(usb, usbatm, UEA_DS_IFACE_NO);		if (ret < 0)			return ret;	}	sc = kzalloc(sizeof(struct uea_softc), GFP_KERNEL);	if (!sc) {		uea_err(usb, "uea_init: not enough memory !\n");		return -ENOMEM;	}	sc->usb_dev = usb;	usbatm->driver_data = sc;	sc->usbatm = usbatm;	sc->modem_index = (modem_index < NB_MODEM) ? modem_index++ : 0;	sc->driver_info = id->driver_info;	/* ADI930 don't support iso */	if (UEA_CHIP_VERSION(id) != ADI930 && use_iso[sc->modem_index]) {		int i;		/* try set fastest alternate for inbound traffic interface */		for (i = FASTEST_ISO_INTF; i > 0; i--)			if (usb_set_interface(usb, UEA_DS_IFACE_NO, i) == 0)				break;		if (i > 0) {			uea_dbg(usb, "set alternate %d for 2 interface\n", i);			uea_info(usb, "using iso mode\n");			usbatm->flags |= UDSL_USE_ISOC | UDSL_IGNORE_EILSEQ;		} else {			uea_err(usb, "setting any alternate failed for "					"2 interface, using bulk mode\n");		}	}	ret = uea_boot(sc);	if (ret < 0) {		kfree(sc);		return ret;	}	create_fs_entries(sc, intf);	return 0;}static void destroy_fs_entries(struct uea_softc *sc, struct usb_interface *intf){	/* sysfs interface */	device_remove_file(&intf->dev, &dev_attr_stat_status);	device_remove_file(&intf->dev, &dev_attr_stat_mflags);	device_remove_file(&intf->dev, &dev_attr_stat_human_status);	device_remove_file(&intf->dev, &dev_attr_stat_delin);	device_remove_file(&intf->dev, &dev_attr_stat_vidcpe);	device_remove_file(&intf->dev, &dev_attr_stat_usrate);	device_remove_file(&intf->dev, &dev_attr_stat_dsrate);	device_remove_file(&intf->dev, &dev_attr_stat_usattenuation);	device_remove_file(&intf->dev, &dev_attr_stat_dsattenuation);	device_remove_file(&intf->dev, &dev_attr_stat_usmargin);	device_remove_file(&intf->dev, &dev_attr_stat_dsmargin);	device_remove_file(&intf->dev, &dev_attr_stat_txflow);	device_remove_file(&intf->dev, &dev_attr_stat_rxflow);	device_remove_file(&intf->dev, &dev_attr_stat_uscorr);	device_remove_file(&intf->dev, &dev_attr_stat_dscorr);	device_remove_file(&intf->dev, &dev_attr_stat_usunc);	device_remove_file(&intf->dev, &dev_attr_stat_dsunc);}static void uea_unbind(struct usbatm_data *usbatm, struct usb_interface *intf){	struct uea_softc *sc = usbatm->driver_data;	destroy_fs_entries(sc, intf);	uea_stop(sc);	kfree(sc);}static struct usbatm_driver uea_usbatm_driver = {	.driver_name = "ueagle-atm",	.bind = uea_bind,	.atm_start = uea_atm_open,	.unbind = uea_unbind,	.heavy_init = uea_heavy,	.bulk_in = UEA_BULK_DATA_PIPE,	.bulk_out = UEA_BULK_DATA_PIPE,	.isoc_in = UEA_ISO_DATA_PIPE,};static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id){	struct usb_device *usb = interface_to_usbdev(intf);	uea_enters(usb);	uea_info(usb, "ADSL device founded vid (%#X) pid (%#X) : %s\n",	       le16_to_cpu(usb->descriptor.idVendor),	       le16_to_cpu(usb->descriptor.idProduct),	       chip_name[UEA_CHIP_VERSION(id)]);	usb_reset_device(usb);	if (UEA_IS_PREFIRM(id))		return uea_load_firmware(usb, UEA_CHIP_VERSION(id));	return usbatm_usb_probe(intf, id, &uea_usbatm_driver);}static void uea_disconnect(struct usb_interface *intf){	struct usb_device *usb = interface_to_usbdev(intf);	int ifnum = intf->altsetting->desc.bInterfaceNumber;	uea_enters(usb);	/* ADI930 has 2 interfaces and eagle 3 interfaces.	 * Pre-firmware device has one interface	 */	if (usb->config->desc.bNumInterfaces != 1 && ifnum == 0) {		mutex_lock(&uea_mutex);		usbatm_usb_disconnect(intf);		mutex_unlock(&uea_mutex);		uea_info(usb, "ADSL device removed\n");	}	uea_leaves(usb);}/* * List of supported VID/PID */static const struct usb_device_id uea_ids[] = {	{USB_DEVICE(ELSA_VID,	ELSA_PID_PREFIRM),	.driver_info = ADI930 | PREFIRM},	{USB_DEVICE(ELSA_VID,	ELSA_PID_PSTFIRM),	.driver_info = ADI930 | PSTFIRM},	{USB_DEVICE(EAGLE_VID,	EAGLE_I_PID_PREFIRM),	.driver_info = EAGLE_I | PREFIRM},	{USB_DEVICE(EAGLE_VID,	EAGLE_I_PID_PSTFIRM),	.driver_info = EAGLE_I | PSTFIRM},	{USB_DEVICE(EAGLE_VID,	EAGLE_II_PID_PREFIRM),	.driver_info = EAGLE_II | PREFIRM},	{USB_DEVICE(EAGLE_VID,	EAGLE_II_PID_PSTFIRM),	.driver_info = EAGLE_II | PSTFIRM},	{USB_DEVICE(EAGLE_VID,	EAGLE_IIC_PID_PREFIRM),	.driver_info = EAGLE_II | PREFIRM},	{USB_DEVICE(EAGLE_VID,	EAGLE_IIC_PID_PSTFIRM),	.driver_info = EAGLE_II | PSTFIRM},	{USB_DEVICE(EAGLE_VID,	EAGLE_III_PID_PREFIRM),	.driver_info = EAGLE_III | PREFIRM},	{USB_DEVICE(EAGLE_VID,	EAGLE_III_PID_PSTFIRM),	.driver_info = EAGLE_III | PSTFIRM},	{USB_DEVICE(USR_VID,	MILLER_A_PID_PREFIRM),	.driver_info = EAGLE_I | PREFIRM},	{USB_DEVICE(USR_VID,	MILLER_A_PID_PSTFIRM),	.driver_info = EAGLE_I | PSTFIRM},	{USB_DEVICE(USR_VID,	MILLER_B_PID_PREFIRM),	.driver_info = EAGLE_I | PREFIRM},	{USB_DEVICE(USR_VID,	MILLER_B_PID_PSTFIRM),	.driver_info = EAGLE_I | PSTFIRM},	{USB_DEVICE(USR_VID,	HEINEKEN_A_PID_PREFIRM),.driver_info = EAGLE_I | PREFIRM},	{USB_DEVICE(USR_VID,	HEINEKEN_A_PID_PSTFIRM),.driver_info = EAGLE_I | PSTFIRM},	{USB_DEVICE(USR_VID,	HEINEKEN_B_PID_PREFIRM),.driver_info = EAGLE_I | PREFIRM},	{USB_DEVICE(USR_VID,	HEINEKEN_B_PID_PSTFIRM),.driver_info = EAGLE_I | PSTFIRM},	{}};/* * USB driver descriptor */static struct usb_driver uea_driver = {	.name = "ueagle-atm",	.id_table = uea_ids,	.probe = uea_probe,	.disconnect = uea_disconnect,};MODULE_DEVICE_TABLE(usb, uea_ids);/** * uea_init - Initialize the module. *      Register to USB subsystem */static int __init uea_init(void){	printk(KERN_INFO "[ueagle-atm] driver " EAGLEUSBVERSION " loaded\n");	usb_register(&uea_driver);	return 0;}module_init(uea_init);/** * uea_exit  -  Destroy module *    Deregister with USB subsystem */static void __exit uea_exit(void){	/*	 * This calls automatically the uea_disconnect method if necessary:	 */	usb_deregister(&uea_driver);	printk(KERN_INFO "[ueagle-atm] driver unloaded\n");}module_exit(uea_exit);MODULE_AUTHOR("Damien Bergamini/Matthieu Castet/Stanislaw W. Gruszka");MODULE_DESCRIPTION("ADI 930/Eagle USB ADSL Modem driver");MODULE_LICENSE("Dual BSD/GPL");

⌨️ 快捷键说明

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