/** * pdc_chassis_info - Return chassis information. * @result: The return buffer. * @chassis_info: The memory buffer address. * @len: The size of the memory buffer address. * * An HVERSION dependent call for returning the chassis information. */ int __init pdc_chassis_info(struct pdc_chassis_info *chassis_info, void *led_info, unsigned long len) { int retval; unsigned long flags; spin_lock_irqsave(&pdc_lock, flags); memcpy(&pdc_result, chassis_info, sizeof(*chassis_info)); memcpy(&pdc_result2, led_info, len); retval = mem_pdc_call(PDC_CHASSIS, PDC_RETURN_CHASSIS_INFO, __pa(pdc_result), __pa(pdc_result2), len); memcpy(chassis_info, pdc_result, sizeof(*chassis_info)); memcpy(led_info, pdc_result2, len); spin_unlock_irqrestore(&pdc_lock, flags); return retval; }
/** * pdc_system_map_find_addrs - Retrieve additional address ranges. * @pdc_addr_info: Return buffer address. * @mod_index: Fixed address module index. * @addr_index: Address range index. * * Retrieve additional information about subsequent address ranges for modules * with multiple address ranges. */ int pdc_system_map_find_addrs(struct pdc_system_map_addr_info *pdc_addr_info, long mod_index, long addr_index) { int retval; unsigned long flags; spin_lock_irqsave(&pdc_lock, flags); retval = mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_ADDRESS, __pa(pdc_result), mod_index, addr_index); convert_to_wide(pdc_result); memcpy(pdc_addr_info, pdc_result, sizeof(*pdc_addr_info)); spin_unlock_irqrestore(&pdc_lock, flags); pdc_addr_info->mod_addr = f_extend(pdc_addr_info->mod_addr); return retval; }
/** * pdc_iodc_read - Read data from the modules IODC. * @actcnt: The actual number of bytes. * @hpa: The HPA of the module for the iodc read. * @index: The iodc entry point. * @iodc_data: A buffer memory for the iodc options. * @iodc_data_size: Size of the memory buffer. * * This PDC call reads from the IODC of the module specified by the hpa * argument. */ int pdc_iodc_read(unsigned long *actcnt, unsigned long hpa, unsigned int index, void *iodc_data, unsigned int iodc_data_size) { int retval; unsigned long flags; spin_lock_irqsave(&pdc_lock, flags); retval = mem_pdc_call(PDC_IODC, PDC_IODC_READ, __pa(pdc_result), hpa, index, __pa(pdc_result2), iodc_data_size); convert_to_wide(pdc_result); *actcnt = pdc_result[0]; memcpy(iodc_data, pdc_result2, iodc_data_size); spin_unlock_irqrestore(&pdc_lock, flags); return retval; }
/** * pdc_get_initiator - Get the SCSI Interface Card params (SCSI ID, SDTR, SE or LVD) * @hwpath: fully bc.mod style path to the device. * @initiator: the array to return the result into * * Get the SCSI operational parameters from PDC. * Needed since HPUX never used BIOS or symbios card NVRAM. * Most ncr/sym cards won't have an entry and just use whatever * capabilities of the card are (eg Ultra, LVD). But there are * several cases where it's useful: * o set SCSI id for Multi-initiator clusters, * o cable too long (ie SE scsi 10Mhz won't support 6m length), * o bus width exported is less than what the interface chip supports. */ int pdc_get_initiator(struct hardware_path *hwpath, struct pdc_initiator *initiator) { int retval; spin_lock_irq(&pdc_lock); /* BCJ-XXXX series boxes. E.G. "9000/785/C3000" */ #define IS_SPROCKETS() (strlen(boot_cpu_data.pdc.sys_model_name) == 14 && \ strncmp(boot_cpu_data.pdc.sys_model_name, "9000/785", 8) == 0) retval = mem_pdc_call(PDC_INITIATOR, PDC_GET_INITIATOR, __pa(pdc_result), __pa(hwpath)); if (retval < PDC_OK) goto out; if (pdc_result[0] < 16) { initiator->host_id = pdc_result[0]; } else { initiator->host_id = -1; } /* * Sprockets and Piranha return 20 or 40 (MT/s). Prelude returns * 1, 2, 5 or 10 for 5, 10, 20 or 40 MT/s, respectively */ switch (pdc_result[1]) { case 1: initiator->factor = 50; break; case 2: initiator->factor = 25; break; case 5: initiator->factor = 12; break; case 25: initiator->factor = 10; break; case 20: initiator->factor = 12; break; case 40: initiator->factor = 10; break; default: initiator->factor = -1; break; } if (IS_SPROCKETS()) { initiator->width = pdc_result[4]; initiator->mode = pdc_result[5]; } else { initiator->width = -1; initiator->mode = -1; } out: spin_unlock_irq(&pdc_lock); return (retval >= PDC_OK); }
/** * pdc_lan_station_id - Get the LAN address. * @lan_addr: The return buffer. * @hpa: The network device HPA. * * Get the LAN station address when it is not directly available from the LAN hardware. */ int pdc_lan_station_id(char *lan_addr, unsigned long hpa) { int retval; unsigned long flags; spin_lock_irqsave(&pdc_lock, flags); retval = mem_pdc_call(PDC_LAN_STATION_ID, PDC_LAN_STATION_ID_READ, __pa(pdc_result), hpa); if (retval < 0) { memset(lan_addr, 0, PDC_LAN_STATION_ID_SIZE); } else { memcpy(lan_addr, pdc_result, PDC_LAN_STATION_ID_SIZE); } spin_unlock_irqrestore(&pdc_lock, flags); return retval; }
/** * pdc_system_map_find_mods - Locate unarchitected modules. * @pdc_mod_info: Return buffer address. * @mod_path: pointer to dev path structure. * @mod_index: fixed address module index. * * To locate and identify modules which reside at fixed I/O addresses, which * do not self-identify via architected bus walks. */ int pdc_system_map_find_mods(struct pdc_system_map_mod_info *pdc_mod_info, struct pdc_module_path *mod_path, long mod_index) { int retval; unsigned long flags; spin_lock_irqsave(&pdc_lock, flags); retval = mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_MODULE, __pa(pdc_result), __pa(pdc_result2), mod_index); convert_to_wide(pdc_result); memcpy(pdc_mod_info, pdc_result, sizeof(*pdc_mod_info)); memcpy(mod_path, pdc_result2, sizeof(*mod_path)); spin_unlock_irqrestore(&pdc_lock, flags); pdc_mod_info->mod_addr = f_extend(pdc_mod_info->mod_addr); return retval; }
/** * pdc_pat_cell_module - Retrieve the cell's module information. * @actcnt: The number of bytes written to mem_addr. * @ploc: The physical location. * @mod: The module index. * @view_type: The view of the address type. * @mem_addr: The return buffer. * * This PDC call returns information about each module attached to the cell * at the specified location. */ int pdc_pat_cell_module(unsigned long *actcnt, unsigned long ploc, unsigned long mod, unsigned long view_type, void *mem_addr) { int retval; static struct pdc_pat_cell_mod_maddr_block result __attribute__ ((aligned (8))); spin_lock_irq(&pdc_lock); retval = mem_pdc_call(PDC_PAT_CELL, PDC_PAT_CELL_MODULE, __pa(pdc_result), ploc, mod, view_type, __pa(&result)); if(!retval) { *actcnt = pdc_result[0]; memcpy(mem_addr, &result, *actcnt); } spin_unlock_irq(&pdc_lock); return retval; }
/** * pdc_lan_station_id - Get the LAN address. * @lan_addr: The return buffer. * @hpa: The network device HPA. * * Get the LAN station address when it is not directly available from the LAN hardware. */ int pdc_lan_station_id(char *lan_addr, unsigned long hpa) { int retval; spin_lock_irq(&pdc_lock); retval = mem_pdc_call(PDC_LAN_STATION_ID, PDC_LAN_STATION_ID_READ, __pa(pdc_result), hpa); if (retval < 0) { /* FIXME: else read MAC from NVRAM */ memset(lan_addr, 0, PDC_LAN_STATION_ID_SIZE); } else { memcpy(lan_addr, pdc_result, PDC_LAN_STATION_ID_SIZE); } spin_unlock_irq(&pdc_lock); return retval; }
/** * pdc_pat_io_pci_cfg_read - Read PCI configuration space. * @pci_addr: PCI configuration space address for which the read request is being made. * @pci_size: Size of read in bytes. Valid values are 1, 2, and 4. * @mem_addr: Pointer to return memory buffer. * */ int pdc_pat_io_pci_cfg_read(unsigned long pci_addr, int pci_size, u32 *mem_addr) { int retval; unsigned long flags; spin_lock_irqsave(&pdc_lock, flags); retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_PCI_CONFIG_READ, __pa(pdc_result), pci_addr, pci_size); switch(pci_size) { case 1: *(u8 *) mem_addr = (u8) pdc_result[0]; case 2: *(u16 *)mem_addr = (u16) pdc_result[0]; case 4: *(u32 *)mem_addr = (u32) pdc_result[0]; } spin_unlock_irqrestore(&pdc_lock, flags); return retval; }
/* * pdc_soft_power_info - Enable soft power switch. * @power_reg: address of soft power register * * Return the absolute address of the soft power switch register */ int __init pdc_soft_power_info(unsigned long *power_reg) { int retval; unsigned long flags; *power_reg = (unsigned long) (-1); spin_lock_irqsave(&pdc_lock, flags); retval = mem_pdc_call(PDC_SOFT_POWER, PDC_SOFT_POWER_INFO, __pa(pdc_result), 0); if (retval == PDC_OK) { convert_to_wide(pdc_result); *power_reg = f_extend(pdc_result[0]); } spin_unlock_irqrestore(&pdc_lock, flags); return retval; }
/** * pdc_model_sysmodel - Get the system model name. * @name: A char array of at least 81 characters. * * Get system model name from PDC ROM (e.g. 9000/715 or 9000/778/B160L). * Using OS_ID_HPUX will return the equivalent of the 'modelname' command * on HP/UX. */ int pdc_model_sysmodel(char *name) { int retval; spin_lock_irq(&pdc_lock); retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_SYSMODEL, __pa(pdc_result), OS_ID_HPUX, __pa(name)); convert_to_wide(pdc_result); if (retval == PDC_OK) { name[pdc_result[0]] = '\0'; /* add trailing '\0' */ } else { name[0] = 0; } spin_unlock_irq(&pdc_lock); return retval; }
/** * pdc_model_capabilities - Returns the platform capabilities. * @capabilities: The return buffer. * * Returns information about platform support for 32- and/or 64-bit * OSes, IO-PDIR coherency, and virtual aliasing. */ int pdc_model_capabilities(unsigned long *capabilities) { int retval; unsigned long flags; spin_lock_irqsave(&pdc_lock, flags); pdc_result[0] = 0; /* preset zero (call may not be implemented!) */ retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_CAPABILITIES, __pa(pdc_result), 0); convert_to_wide(pdc_result); if (retval == PDC_OK) { *capabilities = pdc_result[0]; } else { *capabilities = PDC_MODEL_OS32; } spin_unlock_irqrestore(&pdc_lock, flags); return retval; }
/* get system model name from PDC ROM (e.g. 9000/715 or 9000/778/B160L) */ int pdc_model_sysmodel(char * name) { struct pdc_model_sysmodel sys_model; int retval; ASSERT_ALIGN(&sys_model, 8); ASSERT_ALIGN(name, 4); sys_model.mod_len = 0; retval = mem_pdc_call(PDC_MODEL,PDC_MODEL_SYSMODEL,__pa(&sys_model), OS_ID_HPUX,__pa(name)); if (retval == PDC_RET_OK) name[sys_model.mod_len] = '\0'; /* add trailing '\0' */ else name[0] = 0; return retval; }
int pdc_model_cpuid(struct pdc_model_cpuid *cpu_id) { cpu_id->cpuid = 0; /* preset zero (call maybe not implemented!) */ return mem_pdc_call(PDC_MODEL,6,__pa(cpu_id),0); /* 6="return CPU ID" */ }
int pdc_chassis_warn(struct pdc_chassis_warn *address) { ASSERT_ALIGN(address, 4); return mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_WARN, __pa(address), 0); }
int pdc_cache_info(struct pdc_cache_info *cache_info) { ASSERT_ALIGN(cache_info, 8); return mem_pdc_call(PDC_CACHE,PDC_CACHE_INFO,__pa(cache_info),0); }
int pdc_system_map_find_mods(void *pdc_mod_info, void *mod_path, int index) { return mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_MODULE, __pa(pdc_mod_info), __pa(mod_path), (long)index); }
int pdc_mem_map_hpa(void *r_addr, void *mod_path) { return mem_pdc_call(PDC_MEM_MAP,PDC_MEM_MAP_HPA, __pa(r_addr),__pa(mod_path)); }
int pdc_btlb_info( struct pdc_btlb_info *btlb ) { int status; status = mem_pdc_call(PDC_BLOCK_TLB,PDC_BTLB_INFO,__pa(btlb),0); if (status<0) btlb->max_size = 0; return status; }
/* * pdc_io_reset - Hack to avoid overlapping range registers of Bridges devices. * Primarily a problem on T600 (which parisc-linux doesn't support) but * who knows what other platform firmware might do with this OS "hook". */ void pdc_io_reset(void) { spin_lock_irq(&pdc_lock); mem_pdc_call(PDC_IO, PDC_IO_RESET, 0); spin_unlock_irq(&pdc_lock); }
/* * pdc_io_reset_devices - Hack to Stop USB controller * * If PDC used the usb controller, the usb controller * is still running and will crash the machines during iommu * setup, because of still running DMA. This PDC call * stops the USB controller. * Normally called after calling pdc_io_reset(). */ void pdc_io_reset_devices(void) { spin_lock_irq(&pdc_lock); mem_pdc_call(PDC_IO, PDC_IO_RESET_DEVICES, 0); spin_unlock_irq(&pdc_lock); }
/* id: 0 = cpu revision, 1 = boot-rom-version */ int pdc_model_versions(struct pdc_model_cpuid *cpu_id, int id) { return mem_pdc_call(PDC_MODEL,PDC_MODEL_VERSIONS,__pa(cpu_id),id); }
int pdc_hpa_modules(void *address) { return mem_pdc_call(PDC_HPA, PDC_HPA_MODULES, address); }
/* Similar to PDC_PAT stuff in pdcpat.c - but added for Forte/Allegro boxes */ int pdc_pci_irt_size(void *r_addr, void *hpa) { return mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL_SIZE, __pa(r_addr), hpa); }
/* verify address can be accessed without an HPMC */ int pdc_add_valid(void *address) { ASSERT_ALIGN(address, 4); return mem_pdc_call(PDC_ADD_VALID, PDC_ADD_VALID_VERIFY, (unsigned long)address); }
int pdc_model_info(struct pdc_model *model) { ASSERT_ALIGN(model, 8); return mem_pdc_call(PDC_MODEL,PDC_MODEL_INFO,__pa(model),0); }
/* access the TOD clock */ int pdc_tod_read(struct pdc_tod *tod) { ASSERT_ALIGN(tod, 8); return mem_pdc_call(PDC_TOD, PDC_TOD_READ, __pa(tod), 0); }
int pdc_pci_irt(void *r_addr, void *hpa, void *tbl) { return mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL, __pa(r_addr), hpa, __pa(tbl)); }
int pdc_tod_set(unsigned long sec, unsigned long usec) { return mem_pdc_call(PDC_TOD, PDC_TOD_WRITE, sec, usec); }
int pdc_chassis_disp(unsigned long disp) { return mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_DISP, disp); }