📄 ul_linux.c
字号:
/******************************************************************* uLan Communication - uL_DRV - multiplatform uLan driver ul_linux.c - Linux kernel and module specific part (C) Copyright 1996-2004 by Pavel Pisa - project originator http://cmp.felk.cvut.cz/~pisa (C) Copyright 1996-2004 PiKRON Ltd. http://www.pikron.com (C) Copyright 2002-2004 Petr Smolik The uLan driver project can be used and distributed in compliance with any of next licenses - GPL - GNU Public License See file COPYING for details. - LGPL - Lesser GNU Public License - MPL - Mozilla Public License - and other licenses added by project originator Code can be modified and re-distributed under any combination of the above listed licenses. If contributor does not agree with some of the licenses, he/she can delete appropriate line. WARNING: if you delete all lines, you are not allowed to distribute code or sources in any form. *******************************************************************//*******************************************************************//* Linux kernel and module specific part */ MODULE_SUPPORTED_DEVICE("ul_drv");MODULE_AUTHOR("Pavel Pisa <pisa@cmp.felk.cvut.cz>");MODULE_DESCRIPTION("\uLan communication module ( 9 bit RS-485 protocol )\n\for communication with embedded controllers.\n\It uses i82510 addon card or RS-232 dongle");MODULE_LICENSE("GPL");EXPORT_NO_SYMBOLS;static int ulan_major_dev=ULAN_MAJOR; /* uLan major device number */struct kc_class *ulan_class;#define UL_MINORS 9ul_drv *ul_drv_arr[UL_MINORS]={[0 ... UL_MINORS-1]=NULL};char *chip[UL_MINORS]={NULL,};int chip_specified;#if defined(UL_WITH_PCI) || defined(UL_WITH_USB)char *slot[UL_MINORS]={NULL,};int slot_specified;#endifint my_adr[UL_MINORS]={[0 ... UL_MINORS-1]=2};int my_adr_specified;int baud[UL_MINORS]={[0 ... UL_MINORS-1]=19200};int baud_specified;int baudbase[UL_MINORS]={[0 ... UL_MINORS-1]=0};int baudbase_specified;int irq[UL_MINORS]={0,};int irq_specified;int port[UL_MINORS]={0x3e8 #if (UL_MINORS>1) ,[1 ... UL_MINORS-1]=0 #endif };int port_specified;int debug=-1; /* debug flags */int ul_usb_msg_inpr=0; /* number of concurrent messages sent over USB */#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))module_param_array(chip, charp, &chip_specified, 0);module_param_array(my_adr, int, &my_adr_specified, 0);module_param_array(baud, int, &baud_specified, 0);module_param_array(irq, int, &irq_specified, 0);module_param_array(port, int, &port_specified, 0);module_param_array(baudbase, int, &baudbase_specified, 0);#if defined(UL_WITH_PCI) || defined(UL_WITH_USB)module_param_array(slot, charp, &slot_specified, 0);#endifmodule_param(debug, int, 0);module_param(ul_usb_msg_inpr, int, 0);module_param(ulbuffer, int, 0);#else /* LINUX_VERSION_CODE < 2,6,0 */MODULE_PARM(chip,"1-" __MODULE_STRING(UL_MINORS) "s");MODULE_PARM(my_adr,"1-" __MODULE_STRING(UL_MINORS) "i");MODULE_PARM(baud,"1-" __MODULE_STRING(UL_MINORS) "i");MODULE_PARM(irq,"1-" __MODULE_STRING(UL_MINORS) "i");MODULE_PARM(port,"1-" __MODULE_STRING(UL_MINORS) "i");MODULE_PARM(baudbase,"1-" __MODULE_STRING(UL_MINORS) "i");#if defined(UL_WITH_PCI) || defined(UL_WITH_USB)MODULE_PARM(slot,"1-" __MODULE_STRING(UL_MINORS) "s");#endifMODULE_PARM(debug,"i");MODULE_PARM(ul_usb_msg_inpr,"i");MODULE_PARM(ulbuffer,"i");#endif /* LINUX_VERSION_CODE < 2,6,0 */MODULE_PARM_DESC(chip,"chip type: auto, 82510, 16450, 16950-pci");MODULE_PARM_DESC(my_adr,"uLan address of defined interface");MODULE_PARM_DESC(baud,"define baudrates");MODULE_PARM_DESC(irq,"define irqs");MODULE_PARM_DESC(port,"define ports");MODULE_PARM_DESC(baudbase,"define UART base clock");#if defined(UL_WITH_PCI) || defined(UL_WITH_USB)MODULE_PARM_DESC(slot,"slot type (pci) and specification");#endifMODULE_PARM_DESC(debug,"debug flags (FATAL,CHIO,IRQ,MSG,FAILS,"\ "SEQ,PORTS,FILE,FILT)");MODULE_PARM_DESC(ul_usb_msg_inpr,"used length of Tx fifo in conventor");MODULE_PARM_DESC(ulbuffer,"size of per interface buffer");#ifdef UL_WITH_PCIstatic int /*__devinit*/ ulan_pci_init_one (struct pci_dev *dev, const struct pci_device_id *ent);static void /*__devexit*/ ulan_pci_remove_one (struct pci_dev *dev);MODULE_DEVICE_TABLE(pci, ulan_pci_tbl);static struct pci_driver ulan_pci_driver = { name: "ul_drv", id_table: ulan_pci_tbl, probe: ulan_pci_init_one, remove: ulan_pci_remove_one,};#endif /*UL_WITH_PCI*/#ifdef UL_WITH_USB#if (LINUX_VERSION_CODE < VERSION(2,5,41))static void *ul_usb_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id);static void ul_usb_disconnect(struct usb_device *dev, void *ptr);#else /* 2.5.41 */static int ul_usb_probe(struct usb_interface *intf, const struct usb_device_id *id);static void ul_usb_disconnect(struct usb_interface *intf);#endif /* 2.5.41 */MODULE_DEVICE_TABLE (usb, ulan_usb_tbl);#ifdef CONFIG_USB_DYNAMIC_MINORS/* * if the user wants to use dynamic minor numbers, then we can have up to 256 * devices */#define UL_USB_MINOR_BASE 0#define MAX_DEVICES 256#else/* Get a minor range for your devices from the usb maintainer */#define UL_USB_MINOR_BASE 200/* we can have up to this number of device plugged in at once */#define MAX_DEVICES 16#endif/* usb specific object needed to register this driver with the usb subsystem */static struct usb_driver ul_usb_driver = { name: "ulan_usb", probe: ul_usb_probe, disconnect: ul_usb_disconnect, /*fops: &ul_usb_fops,*/ /* num_minors: MAX_DEVICES,*/ #if (LINUX_VERSION_CODE < VERSION(2,5,8)) minor: UL_USB_MINOR_BASE, #endif id_table: ulan_usb_tbl,};#endif /*UL_WITH_USB*/static int ulan_open(struct inode *inode, struct file *file);static CLOSERET ulan_close(struct inode *inode, struct file *file);static int ulan_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);static RWRET ulan_write(WRITE_PARAMETERS);static RWRET ulan_read(READ_PARAMETERS);static loff_t ulan_lseek(LSEEK_PARAMETERS);static unsigned int ulan_poll(struct file *, poll_table *);/* static struct file_operations ulan_fops */KC_CHRDEV_FOPS_BEG(ulan_fops) KC_FOPS_LSEEK(ulan_lseek)/* lseek */ read:ulan_read, /* read */ write:ulan_write, /* write */ readdir:NULL, /* readdir */ poll:ulan_poll, /* poll */ ioctl:ulan_ioctl, /* ioctl */ mmap:NULL, /* mmap */ open:ulan_open, /* open */ KC_FOPS_FLUSH(NULL) /* flush */ KC_FOPS_RELEASE(ulan_close)/* close/release */ fsync:NULL, /* fsync */ fasync:NULL, /* fasync */ NULL, /* check_media_change */ NULL, /* revalidate */KC_CHRDEV_FOPS_END;/* open ulan device */static int ulan_open(struct inode *inode, struct file *file){ ul_drv *udrv; ul_opdata *opdata; unsigned int minor = kc_dev2minor(inode->i_rdev); #ifdef UL_WITH_DEVFS if(minor==-1){ udrv=file->private_data; }else #endif /* UL_WITH_DEVFS */ { if ((minor >= UL_MINORS)||(minor<0)) return -ENODEV; udrv=ul_drv_arr[minor]; } if (!udrv) return -ENODEV; if(udrv->magic!=UL_DRV_MAGIC) { printk(KERN_CRIT "ulan_open: Wrong uLan MAGIC number!!!\n"); return -ENODEV; } kc_MOD_INC_USE_COUNT; if(!(file->private_data=MALLOC(sizeof(ul_opdata)))) { kc_MOD_DEC_USE_COUNT; return(-ENOMEM); }; opdata=(ul_opdata*)file->private_data; opdata->file=file; opdata->magic=ULOP_MAGIC; opdata->message=NULL; opdata->udrv=udrv; init_waitqueue_head(&opdata->wqrec); opdata->opprew=NULL; opdata->opnext=NULL; opdata->recchain=NULL; opdata->filtchain=NULL; { /* add us onto list of clients of udrv */ ul_opdata *opptr; UL_DRV_LOCK_FINI UL_DRV_LOCK; opptr=udrv->operators; if(opptr) {opptr->opprew=opdata;opdata->opnext=opptr;}; UL_MB(); udrv->operators=opdata; UL_DRV_UNLOCK; }; return 0;};static CLOSERET ulan_close(struct inode *inode, struct file *file){ ul_opchain *opmember; ul_opdata *opdata=(ul_opdata*)file->private_data; if(opdata->magic!=ULOP_MAGIC) panic("ulan_close : BAD opdata magic !!!"); if (opdata->message) ulan_freemsg(opdata); { /* delete us from list of clients of udrv */ ul_drv *udrv; ul_opdata *opptr; UL_DRV_LOCK_FINI UL_DRV_LOCK; if((udrv=opdata->udrv)!=NULL){ if((opptr=opdata->opnext)) opptr->opprew=opdata->opprew; if((opptr=opdata->opprew)) opptr->opnext=opdata->opnext; else udrv->operators=opdata->opnext; } UL_DRV_UNLOCK; if(udrv) if(udrv->irq>0) ul_synchronize_irq(udrv->irq); while((udrv=opdata->udrv)!=NULL){ if(!uld_atomic_test_dfl(udrv,IN_BOTTOM)) break; kc_yield(); } } schedule(); while((opmember=opdata->recchain)) { del_from_opchain(&opdata->recchain,opmember); if(opmember->message) ul_dec_ref_cnt(opmember->message); FREE(opmember); }; while((opmember=opdata->filtchain)) { del_from_opchain(&opdata->filtchain,opmember); FREE(opmember); }; FREE(file->private_data); kc_MOD_DEC_USE_COUNT; return (CLOSERET)0;};static int ulan_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ ul_msginfo msginfo; int ret; ul_opdata *opdata=(ul_opdata*)file->private_data; if(opdata->magic!=ULOP_MAGIC) panic("ulan_ioctl : BAD opdata magic !!!"); switch (cmd) { case UL_DRV_VER : return UL_DRV_VERCODE; case UL_NEWMSG : if(kc_copy_from_user(&msginfo,(void *)arg,sizeof(msginfo))) return -EFAULT; return ulan_newmsg(opdata,&msginfo); case UL_TAILMSG : if(kc_copy_from_user(&msginfo,(void *)arg,sizeof(msginfo))) return -EFAULT; return ulan_tailmsg(opdata,&msginfo); case UL_FREEMSG : return ulan_freemsg(opdata); case UL_ACCEPTMSG : if(kc_copy_to_user((void *)arg,&msginfo,sizeof(msginfo))) return -EFAULT; ret=ulan_acceptmsg(opdata,&msginfo); if(kc_copy_to_user((void *)arg,&msginfo,sizeof(msginfo))) return -EFAULT; return ret; case UL_ACTAILMSG : if(kc_copy_to_user((void *)arg,&msginfo,sizeof(msginfo))) return -EFAULT; ret=ulan_actailmsg(opdata,&msginfo); if(kc_copy_to_user((void *)arg,&msginfo,sizeof(msginfo))) return -EFAULT; return ret; case UL_ADDFILT : if(kc_copy_from_user(&msginfo,(void *)arg,sizeof(msginfo))) return -EFAULT; return ulan_addfilt(opdata,&msginfo); case UL_ABORTMSG : return ulan_abortmsg(opdata); case UL_REWMSG : return ulan_rewmsg(opdata); case UL_KLOGBLL : if(!opdata->udrv) return -ENODEV; printudrvbll(opdata->udrv); #ifdef ENABLE_UL_MEM_CHECK printudrvoperators(opdata->udrv); #endif /* ENABLE_UL_MEM_CHECK */ return 0; case UL_STROKE : if(!opdata->udrv) return -ENODEV; ulan_stroke(opdata->udrv, 1); return 0; case UL_DEBFLG : uld_debug_flg=arg; return 0; case UL_INEPOLL : return ulan_inepoll(opdata); case UL_SETMYADR : return ulan_setmyadr(opdata,arg); #ifdef UL_WITH_IAC case UL_SETIDSTR :{ char idstr[41]; char ch; int ln=0; do{ if(kc_get_user_byte(ch,(char*)arg)) return -EFAULT; if(++arg>=sizeof(idstr)) return -EINVAL; idstr[ln++]=ch; }while(ch);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -