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

📄 ipmi_kcs_intf.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (!(kcs_port || kcs_physaddr)) 		return -ENODEV;		/* Only initialize a port OR a physical address on this call.	   Also, IRQs can go with either ports or addresses. */	if (kcs_port && kcs_physaddr)		return -EINVAL;	new_kcs = kmalloc(kcs_size(), GFP_KERNEL);	if (!new_kcs) {		printk(KERN_ERR "ipmi_kcs: out of memory\n");		return -ENOMEM;	}	/* So we know not to free it unless we have allocated one. */	new_kcs->kcs_sm = NULL;	new_kcs->addr = NULL;	new_kcs->physaddr = kcs_physaddr;	new_kcs->port = kcs_port;	if (kcs_port) {		if (request_region(kcs_port, 2, DEVICE_NAME) == NULL) {			kfree(new_kcs);			printk(KERN_ERR 			       "ipmi_kcs: can't reserve port @ 0x%4.4x\n",		       	       kcs_port);			return -EIO;		}	} else {		if (request_mem_region(kcs_physaddr, 2, DEVICE_NAME) == NULL) {			kfree(new_kcs);			printk(KERN_ERR 			       "ipmi_kcs: can't reserve memory @ 0x%lx\n",		       	       kcs_physaddr);			return -EIO;		}		if ((new_kcs->addr = ioremap(kcs_physaddr, 2)) == NULL) {			kfree(new_kcs);			printk(KERN_ERR 			       "ipmi_kcs: can't remap memory at 0x%lx\n",		       	       kcs_physaddr);			return -EIO;		}	}	new_kcs->kcs_sm = kmalloc(kcs_size(), GFP_KERNEL);	if (!new_kcs->kcs_sm) {		printk(KERN_ERR "ipmi_kcs: out of memory\n");		rv = -ENOMEM;		goto out_err;	}	init_kcs_data(new_kcs->kcs_sm, kcs_port, new_kcs->addr);	spin_lock_init(&(new_kcs->kcs_lock));	spin_lock_init(&(new_kcs->msg_lock));	rv = ipmi_kcs_detect_hardware(kcs_port, new_kcs->addr, new_kcs->kcs_sm);	if (rv) {		if (kcs_port) 			printk(KERN_ERR 			       "ipmi_kcs: No KCS @ port 0x%4.4x\n", 			       kcs_port);		else			printk(KERN_ERR 			       "ipmi_kcs: No KCS @ addr 0x%lx\n", 			       kcs_physaddr);		goto out_err;	}	if (irq != 0) {		rv = request_irq(irq,				 kcs_irq_handler,				 SA_INTERRUPT,				 DEVICE_NAME,				 new_kcs);		if (rv) {			printk(KERN_WARNING			       "ipmi_kcs: %s unable to claim interrupt %d,"			       " running polled\n",			       DEVICE_NAME, irq);			irq = 0;		}	}	new_kcs->irq = irq;	INIT_LIST_HEAD(&(new_kcs->xmit_msgs));	INIT_LIST_HEAD(&(new_kcs->hp_xmit_msgs));	new_kcs->curr_msg = NULL;	atomic_set(&new_kcs->req_events, 0);	new_kcs->run_to_completion = 0;	start_clear_flags(new_kcs);	if (irq) {		new_kcs->kcs_state = KCS_CLEARING_FLAGS_THEN_SET_IRQ;		printk(KERN_INFO 		       "ipmi_kcs: Acquiring BMC @ port=0x%x irq=%d\n",		       kcs_port, irq);	} else {		if (kcs_port)			printk(KERN_INFO 			       "ipmi_kcs: Acquiring BMC @ port=0x%x\n",		       	       kcs_port);		else			printk(KERN_INFO 			       "ipmi_kcs: Acquiring BMC @ addr=0x%lx\n",		       	       kcs_physaddr);	}	rv = ipmi_register_smi(&handlers,			       new_kcs,			       ipmi_version_major,			       ipmi_version_minor,			       &(new_kcs->intf));	if (rv) {		free_irq(irq, new_kcs);		printk(KERN_ERR 		       "ipmi_kcs: Unable to register device: error %d\n",		       rv);		goto out_err;	}	new_kcs->interrupt_disabled = 0;	new_kcs->timer_stopped = 0;	new_kcs->stop_operation = 0;	init_timer(&(new_kcs->kcs_timer));	new_kcs->kcs_timer.data = (long) new_kcs;	new_kcs->kcs_timer.function = kcs_timeout;	new_kcs->last_timeout_jiffies = jiffies;	new_kcs->kcs_timer.expires = jiffies + KCS_TIMEOUT_JIFFIES;	add_timer(&(new_kcs->kcs_timer));	*kcs = new_kcs;	return 0; out_err:	if (kcs_port) 		release_region (kcs_port, 2);	if (new_kcs->addr) 		iounmap(new_kcs->addr);	if (kcs_physaddr) 		release_mem_region(kcs_physaddr, 2);	if (new_kcs->kcs_sm)		kfree(new_kcs->kcs_sm);	kfree(new_kcs);	return rv;}#ifdef CONFIG_ACPI/* Retrieve the base physical address from ACPI tables.  Originally   from Hewlett-Packard simple bmc.c, a GPL KCS driver. */#include <linux/acpi.h>/* A real hack, but everything's not there yet in 2.4. */#define COMPILER_DEPENDENT_UINT64 unsigned long#include <../drivers/acpi/include/acpi.h>#include <../drivers/acpi/include/actypes.h>struct SPMITable {	s8	Signature[4];	u32	Length;	u8	Revision;	u8	Checksum;	s8	OEMID[6];	s8	OEMTableID[8];	s8	OEMRevision[4];	s8	CreatorID[4];	s8	CreatorRevision[4];	s16	InterfaceType;	s16	SpecificationRevision;	u8	InterruptType;	u8	GPE;	s16	Reserved;	u64	GlobalSystemInterrupt;	u8	BaseAddress[12];	u8	UID[4];} __attribute__ ((packed));static unsigned long acpi_find_bmc(void){	acpi_status       status;	acpi_table_header *spmi;	static unsigned long io_base = 0;	if (io_base != 0)		return io_base;	status = acpi_get_firmware_table("SPMI", 1,			ACPI_LOGICAL_ADDRESSING, &spmi);	if (status != AE_OK) {		printk(KERN_ERR "ipmi_kcs: SPMI table not found.\n");		return 0;	}	memcpy(&io_base, ((struct SPMITable *)spmi)->BaseAddress,			sizeof(io_base));		return io_base;}#endifstatic __init int init_ipmi_kcs(void){	int		rv = 0;	int		pos = 0;	int		i = 0;#ifdef CONFIG_ACPI	unsigned long	physaddr = 0;#endif	if (initialized)		return 0;	initialized = 1;	/* First do the "command-line" parameters */	for (i=0; i < KCS_MAX_PARMS; i++) {		rv = init_one_kcs(kcs_ports[i], 				  kcs_irqs[i], 				  0, 				  &(kcs_infos[pos]));		if (rv == 0)			pos++;		rv = init_one_kcs(0, 				  kcs_irqs[i], 				  kcs_addrs[i], 				  &(kcs_infos[pos]));		if (rv == 0)			pos++;	}	/* Only try the defaults if enabled and resources are available	   (because they weren't already specified above). */	if (kcs_trydefaults) {#ifdef CONFIG_ACPI		if ((physaddr = acpi_find_bmc())) {			if (!check_mem_region(physaddr, 2)) {				rv = init_one_kcs(0, 						  0, 						  physaddr, 						  &(kcs_infos[pos]));				if (rv == 0)					pos++;			}		}#endif		if (!check_region(DEFAULT_IO_PORT, 2)) {			rv = init_one_kcs(DEFAULT_IO_PORT, 					  0, 					  0, 					  &(kcs_infos[pos]));			if (rv == 0)				pos++;		}	}	if (kcs_infos[0] == NULL) {		printk("ipmi_kcs: Unable to find any KCS interfaces\n");		return -ENODEV;	} 	return 0;}module_init(init_ipmi_kcs);#ifdef MODULEvoid __exit cleanup_one_kcs(struct kcs_info *to_clean){	int           rv;	unsigned long flags;	if (! to_clean)		return;	/* Tell the timer and interrupt handlers that we are shutting	   down. */	spin_lock_irqsave(&(to_clean->kcs_lock), flags);	spin_lock(&(to_clean->msg_lock));	to_clean->stop_operation = 1;	if (to_clean->irq != 0)		free_irq(to_clean->irq, to_clean);	if (to_clean->port) {		printk(KERN_INFO 		       "ipmi_kcs: Releasing BMC @ port=0x%x\n",		       to_clean->port);		release_region (to_clean->port, 2);	}	if (to_clean->addr) {		printk(KERN_INFO 		       "ipmi_kcs: Releasing BMC @ addr=0x%lx\n",		       to_clean->physaddr);		iounmap(to_clean->addr);		release_mem_region(to_clean->physaddr, 2);	}	spin_unlock(&(to_clean->msg_lock));	spin_unlock_irqrestore(&(to_clean->kcs_lock), flags);	/* Wait for the timer to stop.  This avoids problems with race	   conditions removing the timer here.  Hopefully this will be	   long enough to avoid problems with interrupts still	   running. */	schedule_timeout(2);	while (!to_clean->timer_stopped) {		schedule_timeout(1);	}	rv = ipmi_unregister_smi(to_clean->intf);	if (rv) {		printk(KERN_ERR 		       "ipmi_kcs: Unable to unregister device: errno=%d\n",		       rv);	}	initialized = 0;	kfree(to_clean->kcs_sm);	kfree(to_clean);}static __exit void cleanup_ipmi_kcs(void){	int i;	if (!initialized)		return;	for (i=0; i<KCS_MAX_DRIVERS; i++) {		cleanup_one_kcs(kcs_infos[i]);	}}module_exit(cleanup_ipmi_kcs);#else/* Unfortunately, cmdline::get_options() only returns integers, not   longs.  Since we need ulongs (64-bit physical addresses) parse the    comma-separated list manually.  Arguments can be one of these forms:   m0xaabbccddeeff	A physical memory address without an IRQ   m0xaabbccddeeff:cc	A physical memory address with an IRQ   p0xaabb		An IO port without an IRQ   p0xaabb:cc		An IO port with an IRQ   nodefaults		Suppress trying the default IO port or ACPI address    For example, to pass one IO port with an IRQ, one address, and    suppress the use of the default IO port and ACPI address,   use this option string: ipmi_kcs=p0xCA2:5,m0xFF5B0022,nodefaults   Remember, ipmi_kcs_setup() is passed the string after the equal sign. */static int __init ipmi_kcs_setup(char *str){	unsigned long val;	char *cur, *colon;	int pos;	pos = 0;		cur = strsep(&str, ",");	while ((cur) && (*cur) && (pos < KCS_MAX_PARMS)) {		switch (*cur) {		case 'n':			if (strcmp(cur, "nodefaults") == 0)				kcs_trydefaults = 0;			else				printk(KERN_INFO 				       "ipmi_kcs: bad parameter value %s\n",				       cur);			break;				case 'm':		case 'p':			val = simple_strtoul(cur + 1,					     &colon,					     0);			if (*cur == 'p')				kcs_ports[pos] = val;			else				kcs_addrs[pos] = val;			if (*colon == ':') {				val = simple_strtoul(colon + 1,						     &colon,						     0);				kcs_irqs[pos] = val;			}			pos++;			break;		default:			printk(KERN_INFO 			       "ipmi_kcs: bad parameter value %s\n",			       cur);		}		cur = strsep(&str, ",");	}	return 1;}__setup("ipmi_kcs=", ipmi_kcs_setup);#endifMODULE_LICENSE("GPL");

⌨️ 快捷键说明

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