inventory.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:10k
- /* Copyright (c) 1999 The Puffin Group */
- /* Written by David Kennedy and Alex deVries */
- #include <linux/types.h>
- #include <linux/kernel.h>
- #include <asm/hardware.h>
- #include <asm/io.h>
- #include <asm/pdc.h>
- /*
- ** Debug options
- ** DEBUG_PAT Dump details which PDC PAT provides about ranges/devices.
- */
- #undef DEBUG_PAT
- extern char *parisc_getHWtype(unsigned short hw_type);
- extern struct hp_device * register_module(void *hpa);
- extern void print_devices(char * buf);
- int pdc_hpa_processor(void *address);
- #ifndef __LP64__
- static u8 iodc_data[32] __attribute__ ((aligned (64)));
- static struct pdc_model model __attribute__ ((aligned (8)));
- #endif
- static unsigned long pdc_result[32] __attribute__ ((aligned (8))) = {0,0,0,0};
- static struct pdc_hpa processor_hpa __attribute__ ((aligned (8)));
- static struct pdc_system_map module_result __attribute__ ((aligned (8)));
- static struct pdc_module_path module_path __attribute__ ((aligned (8)));
- #ifdef __LP64__
- #include <asm/pdcpat.h>
- int pdc_pat = 0;
- /*
- ** The module object is filled via PDC_PAT_CELL[Return Cell Module].
- ** If a module is found, register module will get the IODC bytes via
- ** pdc_iodc_read() using the PA view of conf_base_addr for the hpa parameter.
- **
- ** The IO view can be used by PDC_PAT_CELL[Return Cell Module]
- ** only for SBAs and LBAs. This view will cause an invalid
- ** argument error for all other cell module types.
- **
- */
- static int
- pat_query_module( ulong pcell_loc, ulong mod_index)
- {
- extern int num_devices;
- extern struct hp_device devices[];
- pdc_pat_cell_mod_maddr_block_t pa_pdc_cell;
- struct hp_device * dev = &devices[num_devices];
- uint64_t temp; /* 64-bit scratch value */
- long status; /* PDC return value status */
- /* return cell module (PA or Processor view) */
- status = pdc_pat_cell_module(& pdc_result, pcell_loc, mod_index,
- PA_VIEW, & pa_pdc_cell);
- if (status != PDC_RET_OK) {
- /* no more cell modules or error */
- return status;
- }
- /*
- ** save parameters in the hp_device
- ** (The idea being the device driver will call pdc_pat_cell_module()
- ** and store the results in it's own data structure.)
- */
- dev->pcell_loc = pcell_loc;
- dev->mod_index = mod_index;
- /* save generic info returned from the call */
- /* REVISIT: who is the consumer of this? not sure yet... */
- dev->mod_info = pa_pdc_cell.mod_info; /* pass to PAT_GET_ENTITY() */
- dev->pmod_loc = pa_pdc_cell.mod_location;
- dev->mod_path = pa_pdc_cell.mod_path;
- temp = pa_pdc_cell.cba;
- register_module((void *) PAT_GET_CBA(temp)); /* fills in dev->hpa */
- #ifdef DEBUG_PAT
- /* dump what we see so far... */
- switch (PAT_GET_ENTITY(dev->mod_info)) {
- ulong i;
- case PAT_ENTITY_PROC:
- printk ("PAT_ENTITY_PROC: id_eid 0x%lxn", pa_pdc_cell.mod[0]);
- break;
- case PAT_ENTITY_MEM:
- printk ("PAT_ENTITY_MEM: amount 0x%lx min_gni_base 0x%lx min_gni_len 0x%lxn",
- pa_pdc_cell.mod[0],
- pa_pdc_cell.mod[1],
- pa_pdc_cell.mod[2]);
- break;
- case PAT_ENTITY_CA:
- printk ("PAT_ENTITY_CA: %ldn",pcell_loc);
- break;
- case PAT_ENTITY_PBC:
- printk ("PAT_ENTITY_PBC: ");
- goto print_ranges;
- case PAT_ENTITY_SBA:
- printk ("PAT_ENTITY_SBA: ");
- goto print_ranges;
- case PAT_ENTITY_LBA:
- printk ("PAT_ENTITY_LBA: ");
- print_ranges:
- printk ("ranges %ldn", pa_pdc_cell.mod[1]);
- for (i = 0; i < pa_pdc_cell.mod[1]; i++) {
- printk (" %ld: 0x%016lx 0x%016lx 0x%016lxn", i,
- pa_pdc_cell.mod[2+i*3], /* type */
- pa_pdc_cell.mod[3+i*3], /* start */
- pa_pdc_cell.mod[4+i*3]); /* finish (ie end) */
- }
- printk("n");
- break;
- }
- #endif /* DEBUG_PAT */
- return PDC_RET_OK;
- }
- static int do_pat_inventory(void)
- {
- ulong mod_index=0;
- int status;
- ulong cell_num;
- ulong pcell_loc;
- pdc_pat = (pdc_pat_cell_get_number(&pdc_result) == PDC_OK);
- if (!pdc_pat)
- {
- return 0;
- }
- cell_num = pdc_result[0]; /* Cell number call was made */
- /* As of PDC PAT ARS 2.5, ret[1] is NOT architected! */
- pcell_loc = pdc_result[1]; /* Physical location of the cell */
- #ifdef DEBUG_PAT
- printk("CELL_GET_NUMBER: 0x%lx 0x%lxn", cell_num, pcell_loc);
- #endif
- status = pdc_pat_cell_num_to_loc(&pdc_result, cell_num);
- if (status == PDC_BAD_OPTION)
- {
- /* Prelude (and it's successors: Lclass, A400/500) only
- ** implement PDC_PAT_CELL sub-options 0 and 2.
- ** "Home cook'n is best anyhow!"
- */
- } else if (PDC_OK == status) {
- /* so far only Halfdome supports this */
- pcell_loc = pdc_result[0];
- } else {
- panic("WTF? CELL_GET_NUMBER give me invalid cell number?");
- }
- while (PDC_RET_OK == pat_query_module(pcell_loc, mod_index))
- {
- mod_index++;
- }
- return mod_index;
- }
- #endif /* __LP64__ */
- static int do_newer_workstation_inventory(void)
- {
- long status;
- int i, num = 0;
- /* So the idea here is to simply try one SYSTEM_MAP call. If
- that one works, great, otherwise do it another way */
- status = pdc_system_map_find_mods(&module_result,&module_path,0);
- if (status == PDC_RET_OK) {
- /* This is for newer non-PDC-PAT boxes */
- printk("a newer box...n");
- for(i=0, status=PDC_RET_OK; status != PDC_RET_NE_PROC &&
- status != PDC_RET_NE_MOD ;i++) {
- status = pdc_system_map_find_mods(&module_result,&module_path,i);
- if (status == PDC_RET_OK) {
- num++;
- register_module(module_result.mod_addr);
- }
- }
- }
- return (num > 0);
- }
- #ifndef __LP64__
- static struct pdc_memory_map r_addr __attribute__ ((aligned (8)));
- static int really_do_oldhw_inventory(void)
- {
- int i, mod, num = 0;
- int status;
- unsigned int hw_type;
- unsigned int func;
- /* This is undocumented at the time of writing, but basically
- we're setting up mod_path so that bc[0..4]=0xff, and step
- through mod to get the "Path Structure for GSC Modules". If
- it works, use the returned HPA and determine the hardware type. */
- for (i=0;i<6;i++) module_path.bc[i]=0xff;
- for (mod=0;mod<16;mod++) {
- char *stype = NULL;
- module_path.mod=mod;
- status = pdc_mem_map_hpa(&r_addr, &module_path);
- if (status!=PDC_RET_OK) continue;
-
- status = pdc_iodc_read(&pdc_result,(void *) r_addr.hpa,
- 0, &iodc_data,32 );
- if (status!=PDC_RET_OK) continue;
- hw_type = iodc_data[3]&0x1f;
- switch (hw_type)
- {
- case HPHW_NPROC: /* 0 */
- stype="Processor"; break;
- case HPHW_MEMORY: /* 1 */
- stype="Memory"; break;
- case HPHW_B_DMA: /* 2 */
- stype="Type B DMA"; break;
- case HPHW_A_DMA: /* 4 */
- stype="Type A DMA"; break;
- case HPHW_A_DIRECT: /* 5 */
- stype="Type A Direct"; break;
- case HPHW_BCPORT: /* 7 */
- stype="Bus Converter Port"; break;
- case HPHW_CONSOLE: /* 9 */
- stype="Console"; break;
- case HPHW_FIO: /* 10 - Graphics */
- stype="Foreign I/O (Graphics)"; break;
- case HPHW_BA: /* 11 - Bus Adapter */
- stype="Bus Adapter"; break;
- case HPHW_IOA: /* 12 */
- stype="I/O Adapter"; break;
- case HPHW_BRIDGE: /* 13 */
- stype="Bridge"; break;
- case HPHW_FABRIC: /* 14 */
- stype="Fabric"; break;
- case HPHW_FAULTY: /* 31 */
- stype="Faulty HW"; break;
- case HPHW_OTHER: /* 42 */
- default:
- printk("Don't know this hw_type: %dn", hw_type);
- break;
- }
- // This is kluged. But don't want to replicate code for
- // most of the above cases.
- if (stype) {
- #ifdef DBG_PDC_QUERY
- // parisc/kernel/drivers.c
- extern int num_devices;
- extern struct hp_device devices[];
- struct hp_hardware *h;
- #endif
- status = pdc_mem_map_hpa(&r_addr, &module_path);
- if (status==PDC_RET_OK && register_module((void *) r_addr.hpa) != NULL)
- num++;
- if (hw_type == HPHW_BA) {
- /* Now, we're checking for devices for each
- module. I seem to think that the
- modules in question are Lasi (2), 2nd Lasi (6)
- Wax (5). To do this, set bc[5]=0, and set
- bc[4] to the module, and step through the
- functions. */
- for (i=0;i<4;i++) module_path.bc[i]=0xff;
- module_path.bc[4]=mod;
- for (func=0;func<16;func++) {
- module_path.mod = func;
- module_path.bc[5]=0;
- status = pdc_mem_map_hpa(&r_addr, &module_path);
- if (status!=PDC_RET_OK) continue;
- if (register_module((void *) r_addr.hpa) != NULL)
- num++;
- }
- }
- // reset module_path.bc[]
- for (i=0;i<6;i++) module_path.bc[i]=0xff;
- #ifdef DBG_PDC_QUERY
- //
- // Let print_devices() dump everything which is registered.
- //
- h = devices[num_devices-1].reference;
- if (h) stype = h->name;
- printk("Found %s at %dn", stype, module_path.mod);
- #endif
- }
- }
- return num;
- }
- static int
- do_old_inventory(void)
- {
- unsigned int bus_id;
- long status;
- int ok = 0;
- printk(" an older box...n");
- /* Here, we're going to check the model, and decide
- if we should even bother trying. */
- status = pdc_model_info(&model);
- bus_id = (model.hversion >> (4+7) ) &0x1f;
- /* Here, we're checking the HVERSION of the CPU.
- We're only checking the 0th CPU, since it'll
- be the same on an SMP box. */
- switch (bus_id) {
- case 0x4: /* 720, 730, 750, 735, 755 */
- case 0x6: /* 705, 710 */
- case 0x7: /* 715, 725 */
- case 0x8: /* 745, 747, 742 */
- case 0xA: /* 712 and similiar */
- case 0xC: /* 715/64, at least */
- /* Do inventory using MEM_MAP */
- really_do_oldhw_inventory();
- ok = 1;
- break;
- default: /* Everything else */
- printk("This is a very very old machine, with a bus_id of 0x%x.n",bus_id);
- panic("This will probably never run Linux.n");
- }
- return ok;
- }
- #endif /* !__LP64__ */
- void do_inventory(void){
- if((pdc_hpa_processor(&processor_hpa))<0){
- printk(KERN_INFO "Couldn't get the HPA of the processor.n" );
- }
- printk("Searching for devices in PDC firmware... ");
- printk("processor hpa 0x%lxn", processor_hpa.hpa);
- if (!(
- do_newer_workstation_inventory()
- #ifdef __LP64__
- || do_pat_inventory()
- #else /* __LP64__ */
- || do_old_inventory()
- #endif /* __LP64__ */
- ))
- {
- panic("I can't get the hardware inventory on this machine");
- }
- print_devices(NULL);
- }