/** * pdcspath_store - This function writes a path to stable storage. * @entry: A pointer to an allocated pdcspath_entry. * * It can be used in two ways: either by passing it a preset devpath struct * containing an already computed hardware path, or by passing it a device * pointer, from which it'll find out the corresponding hardware path. * For now we do not handle the case where there's an error in writing to the * Stable Storage area, so you'd better not mess up the data :P * * This function expects to be called with @entry->rw_lock write-hold. */ static void pdcspath_store(struct pdcspath_entry *entry) { struct device_path *devpath; BUG_ON(!entry); devpath = &entry->devpath; /* We expect the caller to set the ready flag to 0 if the hardware path struct provided is invalid, so that we know we have to fill it. First case, we don't have a preset hwpath... */ if (!entry->ready) { /* ...but we have a device, map it */ BUG_ON(!entry->dev); device_to_hwpath(entry->dev, (struct hardware_path *)devpath); } /* else, we expect the provided hwpath to be valid. */ DPRINTK("%s: store: 0x%p, 0x%p, addr: 0x%lx\n", __func__, entry, devpath, entry->addr); /* addr, devpath and count must be word aligned */ if (pdc_stable_write(entry->addr, devpath, sizeof(*devpath)) != PDC_OK) { printk(KERN_ERR "%s: an error occured when writing to PDC.\n" "It is likely that the Stable Storage data has been corrupted.\n" "Please check it carefully upon next reboot.\n", __func__); WARN_ON(1); } /* kobject is already registered */ entry->ready = 2; DPRINTK("%s: device: 0x%p\n", __func__, entry->dev); }
/** * pdcs_osdep1_write - Stable Storage OS-Dependent data area 1 input. * @buf: The input buffer to read from. * @count: The number of bytes to be read. * * This can store 16 bytes of OS-Dependent data. We use a byte-by-byte * write approach. It's up to userspace to deal with it when constructing * its input buffer. */ static ssize_t pdcs_osdep1_write(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { u8 in[16]; if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (!buf || !count) return -EINVAL; if (unlikely(pdcs_osid != OS_ID_LINUX)) return -EPERM; if (count > 16) return -EMSGSIZE; /* We'll use a local copy of buf */ memset(in, 0, 16); memcpy(in, buf, count); if (pdc_stable_write(PDCS_ADDR_OSD1, &in, sizeof(in)) != PDC_OK) return -EIO; return count; }
static void pdcspath_store(struct pdcspath_entry *entry) { struct device_path *devpath; BUG_ON(!entry); devpath = &entry->devpath; if (!entry->ready) { BUG_ON(!entry->dev); device_to_hwpath(entry->dev, (struct hardware_path *)devpath); } DPRINTK("%s: store: 0x%p, 0x%p, addr: 0x%lx\n", __func__, entry, devpath, entry->addr); if (pdc_stable_write(entry->addr, devpath, sizeof(*devpath)) != PDC_OK) { printk(KERN_ERR "%s: an error occurred when writing to PDC.\n" "It is likely that the Stable Storage data has been corrupted.\n" "Please check it carefully upon next reboot.\n", __func__); WARN_ON(1); } entry->ready = 2; DPRINTK("%s: device: 0x%p\n", __func__, entry->dev); }
/** * pdcs_osdep2_write - Stable Storage OS-Dependent data area 2 input. * @buf: The input buffer to read from. * @count: The number of bytes to be read. * * This can store pdcs_size - 224 bytes of OS-Dependent data. We use a * byte-by-byte write approach. It's up to userspace to deal with it when * constructing its input buffer. */ static ssize_t pdcs_osdep2_write(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { unsigned long size; unsigned short i; u8 in[4]; if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (!buf || !count) return -EINVAL; if (unlikely(pdcs_size <= 224)) return -ENOSYS; if (unlikely(pdcs_osid != OS_ID_LINUX)) return -EPERM; size = pdcs_size - 224; if (count > size) return -EMSGSIZE; /* We'll use a local copy of buf */ for (i=0; i<count; i+=4) { memset(in, 0, 4); memcpy(in, buf+i, (count-i < 4) ? count-i : 4); if (unlikely(pdc_stable_write(PDCS_ADDR_OSD2 + i, &in, sizeof(in)) != PDC_OK)) return -EIO; } return count; }
static int __init parisc_init(void) { u32 osid = (OS_ID_LINUX << 16); parisc_proc_mkdir(); parisc_init_resources(); do_device_inventory(); /* probe for hardware */ parisc_pdc_chassis_init(); /* set up a new led state on systems shipped LED State panel */ pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BSTART); /* tell PDC we're Linux. Nevermind failure. */ pdc_stable_write(0x40, &osid, sizeof(osid)); /* start with known state */ flush_cache_all_local(); flush_tlb_all_local(NULL); processor_init(); #ifdef CONFIG_SMP pr_info("CPU(s): %d out of %d %s at %d.%06d MHz online\n", num_online_cpus(), num_present_cpus(), #else pr_info("CPU(s): 1 x %s at %d.%06d MHz\n", #endif boot_cpu_data.cpu_name, boot_cpu_data.cpu_hz / 1000000, boot_cpu_data.cpu_hz % 1000000 ); apply_alternatives_all(); parisc_setup_cache_timing(); /* These are in a non-obvious order, will fix when we have an iotree */ #if defined(CONFIG_IOSAPIC) iosapic_init(); #endif #if defined(CONFIG_IOMMU_SBA) sba_init(); #endif #if defined(CONFIG_PCI_LBA) lba_init(); #endif /* CCIO before any potential subdevices */ #if defined(CONFIG_IOMMU_CCIO) ccio_init(); #endif /* * Need to register Asp & Wax before the EISA adapters for the IRQ * regions. EISA must come before PCI to be sure it gets IRQ region * 0. */ #if defined(CONFIG_GSC_LASI) || defined(CONFIG_GSC_WAX) gsc_init(); #endif #ifdef CONFIG_EISA eisa_init(); #endif #if defined(CONFIG_HPPB) hppb_init(); #endif #if defined(CONFIG_GSC_DINO) dino_init(); #endif #ifdef CONFIG_CHASSIS_LCD_LED register_led_regions(); /* register LED port info in procfs */ #endif return 0; }