static int pci_sal_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value) { int result = 0; u64 data = 0; if (!value || (seg > 255) || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) return -EINVAL; result = ia64_sal_pci_config_read(PCI_SAL_ADDRESS(seg, bus, dev, fn, reg), len, &data); *value = (u32) data; return result; }
int raw_pci_read(unsigned int seg, unsigned int bus, unsigned int devfn, int reg, int len, u32 *value) { u64 addr, data = 0; int mode, result; if (!value || (seg > 65535) || (bus > 255) || (devfn > 255) || (reg > 4095)) return -EINVAL; if ((seg | reg) <= 255) { addr = PCI_SAL_ADDRESS(seg, bus, devfn, reg); mode = 0; } else { addr = PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg); mode = 1; } result = ia64_sal_pci_config_read(addr, mode, len, &data); if (result != 0) return -EINVAL; *value = (u32) data; return 0; }
struct sal_ret_values sal_emulator (long index, unsigned long in1, unsigned long in2, unsigned long in3, unsigned long in4, unsigned long in5, unsigned long in6, unsigned long in7) { struct ia64_sal_retval ret_stuff; unsigned long r9 = 0; unsigned long r10 = 0; long r11 = 0; long status; debugger_event(XEN_IA64_DEBUG_ON_SAL); status = 0; switch (index) { case SAL_FREQ_BASE: if (likely(!running_on_sim)) status = ia64_sal_freq_base(in1,&r9,&r10); else switch (in1) { case SAL_FREQ_BASE_PLATFORM: r9 = 200000000; break; case SAL_FREQ_BASE_INTERVAL_TIMER: r9 = 700000000; break; case SAL_FREQ_BASE_REALTIME_CLOCK: r9 = 1; break; default: status = -1; break; } break; case SAL_PCI_CONFIG_READ: if (current->domain == dom0) { u64 value; // note that args 2&3 are swapped!! status = ia64_sal_pci_config_read(in1,in3,in2,&value); r9 = value; } else printk("NON-PRIV DOMAIN CALLED SAL_PCI_CONFIG_READ\n"); break; case SAL_PCI_CONFIG_WRITE: if (current->domain == dom0) { if (((in1 & ~0xffffffffUL) && (in4 == 0)) || (in4 > 1) || (in2 > 8) || (in2 & (in2-1))) printk("*** SAL_PCI_CONF_WRITE?!?(adr=0x%lx,typ=0x%lx,sz=0x%lx,val=0x%lx)\n", in1,in4,in2,in3); // note that args are in a different order!! status = ia64_sal_pci_config_write(in1,in4,in2,in3); } else printk("NON-PRIV DOMAIN CALLED SAL_PCI_CONFIG_WRITE\n"); break; case SAL_SET_VECTORS: if (in1 == SAL_VECTOR_OS_BOOT_RENDEZ) { if (in4 != 0 || in5 != 0 || in6 != 0 || in7 != 0) { /* Sanity check: cs_length1 must be 0, second vector is reserved. */ status = -2; } else { struct domain *d = current->domain; d->arch.sal_data->boot_rdv_ip = in2; d->arch.sal_data->boot_rdv_r1 = in3; } } else { if (in1 > sizeof(sal_vectors)/sizeof(sal_vectors[0])-1) BUG(); sal_vectors[in1].vector_type = in1; sal_vectors[in1].handler_addr1 = in2; sal_vectors[in1].gp1 = in3; sal_vectors[in1].handler_len1 = in4; sal_vectors[in1].handler_addr2 = in5; sal_vectors[in1].gp2 = in6; sal_vectors[in1].handler_len2 = in7; } break; case SAL_GET_STATE_INFO: if (current->domain == dom0) { sal_queue_entry_t *e; unsigned long flags; struct smp_call_args_t arg; spin_lock_irqsave(&sal_queue_lock, flags); if (!sal_queue || list_empty(&sal_queue[in1])) { sal_log_record_header_t header; XEN_GUEST_HANDLE(void) handle = *(XEN_GUEST_HANDLE(void)*)&in3; IA64_SAL_DEBUG("SAL_GET_STATE_INFO(%s) " "no sal_queue entry found.\n", rec_name[in1]); memset(&header, 0, sizeof(header)); if (copy_to_guest(handle, &header, 1)) { printk("sal_emulator: " "SAL_GET_STATE_INFO can't copy " "empty header to user: 0x%lx\n", in3); } status = IA64_SAL_NO_INFORMATION_AVAILABLE; r9 = 0; spin_unlock_irqrestore(&sal_queue_lock, flags); break; } e = list_entry(sal_queue[in1].next, sal_queue_entry_t, list); list_del(&e->list); spin_unlock_irqrestore(&sal_queue_lock, flags); IA64_SAL_DEBUG("SAL_GET_STATE_INFO(%s <= %s) " "on CPU#%d.\n", rec_name[e->sal_info_type], rec_name[in1], e->cpuid); arg.type = e->sal_info_type; arg.target = in3; arg.corrected = !!((in1 != e->sal_info_type) && (e->sal_info_type == SAL_INFO_TYPE_MCA)); arg.domain = current->domain; arg.status = 0; if (e->cpuid == smp_processor_id()) { IA64_SAL_DEBUG("SAL_GET_STATE_INFO: local\n"); get_state_info_on(&arg); } else { int ret; IA64_SAL_DEBUG("SAL_GET_STATE_INFO: remote\n"); ret = smp_call_function_single(e->cpuid, get_state_info_on, &arg, 0, 1); if (ret < 0) { printk("SAL_GET_STATE_INFO " "smp_call_function_single error:" " %d\n", ret); arg.ret = 0; arg.status = IA64_SAL_NO_INFORMATION_AVAILABLE; } } r9 = arg.ret; status = arg.status; if (r9 == 0) { xfree(e); } else { /* Re-add the entry to sal_queue */ spin_lock_irqsave(&sal_queue_lock, flags); list_add(&e->list, &sal_queue[in1]); spin_unlock_irqrestore(&sal_queue_lock, flags); } } else {