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 + -
显示快捷键?