ipmi_si_intf.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 2,083 行 · 第 1/4 页

C
2,083
字号
	printk("ipmi_si: Trying \"%s\" at I/O port 0x%x\n",	       si_type[intf_num], ports[intf_num]);	return 0;}static unsigned char mem_inb(struct si_sm_io *io, unsigned int offset){	return readb((io->addr)+offset);}static void mem_outb(struct si_sm_io *io, unsigned int offset,		     unsigned char b){	writeb(b, (io->addr)+offset);}static int mem_setup(struct smi_info *info){	unsigned long *addr = info->io.info;	if (!addr || (!*addr))		return -ENODEV;	if (request_mem_region(*addr, info->io_size, DEVICE_NAME) == NULL)		return -EIO;	info->io.addr = ioremap(*addr, info->io_size);	if (info->io.addr == NULL) {		release_mem_region(*addr, info->io_size);		return -EIO;	}	return 0;}static void mem_cleanup(struct smi_info *info){	unsigned long *addr = info->io.info;	if (info->io.addr) {		iounmap(info->io.addr);		release_mem_region(*addr, info->io_size);	}	kfree(info);}static int try_init_mem(int intf_num, struct smi_info **new_info){	struct smi_info *info;	if (!addrs[intf_num])		return -ENODEV;	if (!is_new_interface(intf_num, IPMI_MEM_ADDR_SPACE,			      addrs[intf_num]))		return -ENODEV;	info = kmalloc(sizeof(*info), GFP_KERNEL);	if (!info) {		printk(KERN_ERR "ipmi_si: Could not allocate SI data (2)\n");		return -ENOMEM;	}	memset(info, 0, sizeof(*info));	info->io_setup = mem_setup;	info->io_cleanup = mem_cleanup;	info->io.inputb = mem_inb;	info->io.outputb = mem_outb;	info->io.info = (void *) addrs[intf_num];	info->io.addr = NULL;	info->irq = 0;	info->irq_setup = NULL;	*new_info = info;	if (si_type[intf_num] == NULL)		si_type[intf_num] = "kcs";	printk("ipmi_si: Trying \"%s\" at memory address 0x%lx\n",	       si_type[intf_num], addrs[intf_num]);	return 0;}#ifdef CONFIG_ACPI_INTERPRETER#include <linux/acpi.h>/* Once we get an ACPI failure, we don't try any more, because we go   through the tables sequentially.  Once we don't find a table, there   are no more. */static int acpi_failure = 0;/* For GPE-type interrupts. */void ipmi_acpi_gpe(void *context){	struct smi_info *smi_info = context;	unsigned long   flags;#ifdef DEBUG_TIMING	struct timeval t;#endif	spin_lock_irqsave(&(smi_info->si_lock), flags);	spin_lock(&smi_info->count_lock);	smi_info->interrupts++;	spin_unlock(&smi_info->count_lock);	if (smi_info->stop_operation)		goto out;#ifdef DEBUG_TIMING	do_gettimeofday(&t);	printk("**ACPI_GPE: %d.%9.9d\n", t.tv_sec, t.tv_usec);#endif	smi_event_handler(smi_info, 0); out:	spin_unlock_irqrestore(&(smi_info->si_lock), flags);}static int acpi_gpe_irq_setup(struct smi_info *info){	acpi_status status;	if (!info->irq)		return 0;	/* FIXME - is level triggered right? */	status = acpi_install_gpe_handler(NULL,					  info->irq,					  ACPI_GPE_LEVEL_TRIGGERED,					  ipmi_acpi_gpe,					  info);	if (status != AE_OK) {		printk(KERN_WARNING		       "ipmi_si: %s unable to claim ACPI GPE %d,"		       " running polled\n",		       DEVICE_NAME, info->irq);		info->irq = 0;		return -EINVAL;	} else {		printk("  Using ACPI GPE %d\n", info->irq);		return 0;	}}static void acpi_gpe_irq_cleanup(struct smi_info *info){	if (!info->irq)		return;	acpi_remove_gpe_handler(NULL, info->irq, ipmi_acpi_gpe);}/* * Defined at * http://h21007.www2.hp.com/dspp/files/unprotected/devresource/Docs/TechPapers/IA64/hpspmi.pdf */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];	u8	InterfaceType;	u8	IPMIlegacy;	s16	SpecificationRevision;	/*	 * Bit 0 - SCI interrupt supported	 * Bit 1 - I/O APIC/SAPIC	 */	u8	InterruptType;	/* If bit 0 of InterruptType is set, then this is the SCI           interrupt in the GPEx_STS register. */	u8	GPE;	s16	Reserved;	/* If bit 1 of InterruptType is set, then this is the I/O           APIC/SAPIC interrupt. */	u32	GlobalSystemInterrupt;	/* The actual register address. */	struct acpi_generic_address addr;	u8	UID[4];	s8      spmi_id[1]; /* A '\0' terminated array starts here. */};static int try_init_acpi(int intf_num, struct smi_info **new_info){	struct smi_info  *info;	acpi_status      status;	struct SPMITable *spmi;	char             *io_type;	u8 		 addr_space;	if (acpi_failure)		return -ENODEV;	status = acpi_get_firmware_table("SPMI", intf_num+1,					 ACPI_LOGICAL_ADDRESSING,					 (struct acpi_table_header **) &spmi);	if (status != AE_OK) {		acpi_failure = 1;		return -ENODEV;	}	if (spmi->IPMIlegacy != 1) {	    printk(KERN_INFO "IPMI: Bad SPMI legacy %d\n", spmi->IPMIlegacy);  	    return -ENODEV;	}	if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)		addr_space = IPMI_MEM_ADDR_SPACE;	else		addr_space = IPMI_IO_ADDR_SPACE;	if (!is_new_interface(-1, addr_space, spmi->addr.address))		return -ENODEV;	/* Figure out the interface type. */	switch (spmi->InterfaceType)	{	case 1:	/* KCS */		si_type[intf_num] = "kcs";		break;	case 2:	/* SMIC */		si_type[intf_num] = "smic";		break;	case 3:	/* BT */		si_type[intf_num] = "bt";		break;	default:		printk(KERN_INFO "ipmi_si: Unknown ACPI/SPMI SI type %d\n",			spmi->InterfaceType);		return -EIO;	}	info = kmalloc(sizeof(*info), GFP_KERNEL);	if (!info) {		printk(KERN_ERR "ipmi_si: Could not allocate SI data (3)\n");		return -ENOMEM;	}	memset(info, 0, sizeof(*info));	if (spmi->InterruptType & 1) {		/* We've got a GPE interrupt. */		info->irq = spmi->GPE;		info->irq_setup = acpi_gpe_irq_setup;		info->irq_cleanup = acpi_gpe_irq_cleanup;	} else if (spmi->InterruptType & 2) {		/* We've got an APIC/SAPIC interrupt. */		info->irq = spmi->GlobalSystemInterrupt;		info->irq_setup = std_irq_setup;		info->irq_cleanup = std_irq_cleanup;	} else {		/* Use the default interrupt setting. */		info->irq = 0;		info->irq_setup = NULL;	}	if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {		io_type = "memory";		info->io_setup = mem_setup;		info->io_cleanup = mem_cleanup;		addrs[intf_num] = spmi->addr.address;		info->io.inputb = mem_inb;		info->io.outputb = mem_outb;		info->io.info = &(addrs[intf_num]);	} else if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) {		io_type = "I/O";		info->io_setup = port_setup;		info->io_cleanup = port_cleanup;		ports[intf_num] = spmi->addr.address;		info->io.inputb = port_inb;		info->io.outputb = port_outb;		info->io.info = &(ports[intf_num]);	} else {		kfree(info);		printk("ipmi_si: Unknown ACPI I/O Address type\n");		return -EIO;	}	*new_info = info;	printk("ipmi_si: ACPI/SPMI specifies \"%s\" %s SI @ 0x%lx\n",	       si_type[intf_num], io_type, (unsigned long) spmi->addr.address);	return 0;}#endif#ifdef CONFIG_X86typedef struct dmi_ipmi_data{	u8   		type;	u8   		addr_space;	unsigned long	base_addr;	u8   		irq;}dmi_ipmi_data_t;typedef struct dmi_header{	u8	type;	u8	length;	u16	handle;}dmi_header_t;static int decode_dmi(dmi_header_t *dm, dmi_ipmi_data_t *ipmi_data){	u8		*data = (u8 *)dm;	unsigned long  	base_addr;	ipmi_data->type = data[0x04];	memcpy(&base_addr,&data[0x08],sizeof(unsigned long));	if (base_addr & 1) {		/* I/O */		base_addr &= 0xFFFE;		ipmi_data->addr_space = IPMI_IO_ADDR_SPACE;	}	else {		/* Memory */		ipmi_data->addr_space = IPMI_MEM_ADDR_SPACE;	}	ipmi_data->base_addr = base_addr;	ipmi_data->irq = data[0x11];	if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr))	    return 0;	memset(ipmi_data,0,sizeof(dmi_ipmi_data_t));	return -1;}static int dmi_table(u32 base, int len, int num,	dmi_ipmi_data_t *ipmi_data){	u8 		  *buf;	struct dmi_header *dm;	u8 		  *data;	int 		  i=1;	int		  status=-1;	buf = ioremap(base, len);	if(buf==NULL)		return -1;	data = buf;	while(i<num && (data - buf) < len)	{		dm=(dmi_header_t *)data;		if((data-buf+dm->length) >= len)        		break;		if (dm->type == 38) {			if (decode_dmi(dm, ipmi_data) == 0) {				status = 0;				break;			}		}	        data+=dm->length;		while((data-buf) < len && (*data || data[1]))			data++;		data+=2;		i++;	}	iounmap(buf);	return status;}inline static int dmi_checksum(u8 *buf){	u8   sum=0;	int  a;	for(a=0; a<15; a++)		sum+=buf[a];	return (sum==0);}static int dmi_iterator(dmi_ipmi_data_t *ipmi_data){	u8   buf[15];	u32  fp=0xF0000;#ifdef CONFIG_SIMNOW	return -1;#endif	while(fp < 0xFFFFF)	{		isa_memcpy_fromio(buf, fp, 15);		if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf))		{			u16 num=buf[13]<<8|buf[12];			u16 len=buf[7]<<8|buf[6];			u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];			if(dmi_table(base, len, num, ipmi_data) == 0)				return 0;		}		fp+=16;	}	return -1;}static int try_init_smbios(int intf_num, struct smi_info **new_info){	struct smi_info   *info;	dmi_ipmi_data_t   ipmi_data;	char              *io_type;	int               status;	status = dmi_iterator(&ipmi_data);	if (status < 0)		return -ENODEV;	switch(ipmi_data.type) {		case 0x01: /* KCS */			si_type[intf_num] = "kcs";			break;		case 0x02: /* SMIC */			si_type[intf_num] = "smic";			break;		case 0x03: /* BT */			si_type[intf_num] = "bt";			break;		default:			printk("ipmi_si: Unknown SMBIOS SI type.\n");			return -EIO;	}	info = kmalloc(sizeof(*info), GFP_KERNEL);	if (!info) {		printk(KERN_ERR "ipmi_si: Could not allocate SI data (4)\n");		return -ENOMEM;	}	memset(info, 0, sizeof(*info));	if (ipmi_data.addr_space == 1) {		io_type = "memory";		info->io_setup = mem_setup;		info->io_cleanup = mem_cleanup;		addrs[intf_num] = ipmi_data.base_addr;		info->io.inputb = mem_inb;		info->io.outputb = mem_outb;		info->io.info = &(addrs[intf_num]);	} else if (ipmi_data.addr_space == 2) {		io_type = "I/O";		info->io_setup = port_setup;		info->io_cleanup = port_cleanup;		ports[intf_num] = ipmi_data.base_addr;		info->io.inputb = port_inb;		info->io.outputb = port_outb;		info->io.info = &(ports[intf_num]);	} else {		kfree(info);		printk("ipmi_si: Unknown SMBIOS I/O Address type.\n");		return -EIO;	}	irqs[intf_num] = ipmi_data.irq;	*new_info = info;	printk("ipmi_si: Found SMBIOS-specified state machine at %s"	       " address 0x%lx\n",	       io_type, (unsigned long)ipmi_data.base_addr);	return 0;}#endif /* CONFIG_X86 */#ifdef CONFIG_PCI#define PCI_ERMC_CLASSCODE  0x0C0700#define PCI_HP_VENDOR_ID    0x103C#define PCI_MMC_DEVICE_ID   0x121A#define PCI_MMC_ADDR_CW     0x10/* Avoid more than one attempt to probe pci smic. */static int pci_smic_checked = 0;static int find_pci_smic(int intf_num, struct smi_info **new_info){	struct smi_info  *info;	int              error;	struct pci_dev   *pci_dev = NULL;	u16    		 base_addr;	int              fe_rmc = 0;	if (pci_smic_checked)		return -ENODEV;	pci_smic_checked = 1;	if ((pci_dev = pci_find_device(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID,				       NULL)))		;	else if ((pci_dev = pci_find_class(PCI_ERMC_CLASSCODE, NULL)) &&		 pci_dev->subsystem_vendor == PCI_HP_VENDOR_ID)		fe_rmc = 1;	else		return -ENODEV;

⌨️ 快捷键说明

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