📄 prom.c
字号:
* in general, as there does not appear to be a slb-size OF * entry. At least in Condor and earlier. DRENG */ _naca->slb_size = 64;#ifdef DEBUG_PROM prom_print(RELOC("naca->processorCount = 0x")); prom_print_hex(_naca->processorCount); prom_print_nl(); prom_print(RELOC("naca->physicalMemorySize = 0x")); prom_print_hex(_naca->physicalMemorySize); prom_print_nl(); prom_print(RELOC("naca->pftSize = 0x")); prom_print_hex(_naca->pftSize); prom_print_nl(); prom_print(RELOC("naca->dCacheL1LineSize = 0x")); prom_print_hex(_naca->dCacheL1LineSize); prom_print_nl(); prom_print(RELOC("naca->dCacheL1LogLineSize = 0x")); prom_print_hex(_naca->dCacheL1LogLineSize); prom_print_nl(); prom_print(RELOC("naca->dCacheL1LinesPerPage = 0x")); prom_print_hex(_naca->dCacheL1LinesPerPage); prom_print_nl(); prom_print(RELOC("naca->iCacheL1LineSize = 0x")); prom_print_hex(_naca->iCacheL1LineSize); prom_print_nl(); prom_print(RELOC("naca->iCacheL1LogLineSize = 0x")); prom_print_hex(_naca->iCacheL1LogLineSize); prom_print_nl(); prom_print(RELOC("naca->iCacheL1LinesPerPage = 0x")); prom_print_hex(_naca->iCacheL1LinesPerPage); prom_print_nl(); prom_print(RELOC("naca->serialPortAddr = 0x")); prom_print_hex(_naca->serialPortAddr); prom_print_nl(); prom_print(RELOC("naca->interrupt_controller = 0x")); prom_print_hex(_naca->interrupt_controller); prom_print_nl(); prom_print(RELOC("naca->platform = 0x")); prom_print_hex(_naca->platform); prom_print_nl(); prom_print(RELOC("prom_initialize_naca: end...\n"));#endif return mem;}static unsigned long __initprom_initialize_lmb(unsigned long mem){ phandle node; char type[64]; unsigned long i, offset = reloc_offset(); struct prom_t *_prom = PTRRELOC(&prom); union lmb_reg_property reg; unsigned long lmb_base, lmb_size; unsigned long num_regs, bytes_per_reg = (_prom->encode_phys_size*2)/8;#ifdef CONFIG_MSCHUNKS unsigned long max_addr = 0;#if 1 /* Fix me: 630 3G-4G IO hack here... -Peter (PPPBBB) */ unsigned long io_base = 3UL<<30; unsigned long io_size = 1UL<<30; unsigned long have_630 = 1; /* assume we have a 630 */#else unsigned long io_base = <real io base here>; unsigned long io_size = <real io size here>;#endif#endif /* CONFIG_MSCHUNKS */ lmb_init(); for (node = 0; prom_next_node(&node); ) { type[0] = 0; call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"), type, sizeof(type)); if (strcmp(type, RELOC("memory"))) continue; num_regs = call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"), ®, sizeof(reg)) / bytes_per_reg; for (i=0; i < num_regs ;i++) { if (_prom->encode_phys_size == 32) { lmb_base = reg.addr32[i].address; lmb_size = reg.addr32[i].size; } else { lmb_base = reg.addr64[i].address; lmb_size = reg.addr64[i].size; }#ifdef CONFIG_MSCHUNKS if ( lmb_addrs_overlap(lmb_base,lmb_size, io_base,io_size) ) { /* If we really have dram here, then we don't * have a 630! -Peter */ have_630 = 0; }#endif /* CONFIG_MSCHUNKS */ if ( lmb_add(lmb_base, lmb_size) < 0 ) prom_print(RELOC("Too many LMB's, discarding this one...\n"));#ifdef CONFIG_MSCHUNKS else if ( max_addr < (lmb_base+lmb_size-1) ) max_addr = lmb_base+lmb_size-1;#endif /* CONFIG_MSCHUNKS */ } }#ifdef CONFIG_MSCHUNKS if ( have_630 && lmb_addrs_overlap(0,max_addr,io_base,io_size) ) lmb_add_io(io_base, io_size);#endif /* CONFIG_MSCHUNKS */ lmb_analyze();#ifdef DEBUG_PROM prom_dump_lmb();#endif /* DEBUG_PROM */#ifdef CONFIG_MSCHUNKS mem = prom_initialize_mschunks(mem);#ifdef DEBUG_PROM prom_dump_mschunks_mapping();#endif /* DEBUG_PROM */#endif /* CONFIG_MSCHUNKS */ return mem;}static unsigned long __initprom_instantiate_rtas(unsigned long mem){ unsigned long offset = reloc_offset(); struct prom_t *_prom = PTRRELOC(&prom); struct rtas_t *_rtas = PTRRELOC(&rtas); struct naca_struct *_naca = RELOC(naca); ihandle prom_rtas; u32 getprop_rval;#ifdef DEBUG_PROM prom_print(RELOC("prom_instantiate_rtas: start...\n"));#endif prom_rtas = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/rtas")); if (prom_rtas != (ihandle) -1) { char hypertas_funcs[1024]; int rc; if ((rc = call_prom(RELOC("getprop"), 4, 1, prom_rtas, RELOC("ibm,hypertas-functions"), hypertas_funcs, sizeof(hypertas_funcs))) > 0) { _naca->platform = PLATFORM_PSERIES_LPAR; } call_prom(RELOC("getprop"), 4, 1, prom_rtas, RELOC("rtas-size"), &getprop_rval, sizeof(getprop_rval)); _rtas->size = getprop_rval; prom_print(RELOC("instantiating rtas")); if (_rtas->size != 0) { /* * Ask OF for some space for RTAS. * Actually OF has bugs so we just arbitrarily * use memory at the 6MB point. */ // The new code... mem = PAGE_ALIGN(mem); _rtas->base = mem + offset - KERNELBASE; mem += _rtas->size; prom_print(RELOC(" at 0x")); prom_print_hex(_rtas->base); prom_rtas = (ihandle)call_prom(RELOC("open"), 1, 1, RELOC("/rtas")); prom_print(RELOC("...")); if ((long)call_prom(RELOC("call-method"), 3, 2, RELOC("instantiate-rtas"), prom_rtas, _rtas->base) >= 0) { _rtas->entry = (long)_prom->args.rets[1]; } } if (_rtas->entry <= 0) { prom_print(RELOC(" failed\n")); } else { prom_print(RELOC(" done\n")); }#ifdef DEBUG_PROM prom_print(RELOC("rtas->base = 0x")); prom_print_hex(_rtas->base); prom_print_nl(); prom_print(RELOC("rtas->entry = 0x")); prom_print_hex(_rtas->entry); prom_print_nl(); prom_print(RELOC("rtas->size = 0x")); prom_print_hex(_rtas->size); prom_print_nl();#endif }#ifdef DEBUG_PROM prom_print(RELOC("prom_instantiate_rtas: end...\n"));#endif return mem;}unsigned long prom_strtoul(const char *cp){ unsigned long result = 0,value; while (*cp) { value = *cp-'0'; result = result*10 + value; cp++; } return result;}#ifdef CONFIG_MSCHUNKSstatic unsigned longprom_initialize_mschunks(unsigned long mem){ unsigned long offset = reloc_offset(); struct lmb *_lmb = PTRRELOC(&lmb); struct msChunks *_msChunks = PTRRELOC(&msChunks); unsigned long i, pchunk = 0; unsigned long addr_range = _lmb->memory.size + _lmb->memory.iosize; unsigned long chunk_size = _lmb->memory.lcd_size; mem = msChunks_alloc(mem, addr_range / chunk_size, chunk_size); /* First create phys -> abs mapping for memory/dram */ for (i=0; i < _lmb->memory.cnt ;i++) { unsigned long base = _lmb->memory.region[i].base; unsigned long size = _lmb->memory.region[i].size; unsigned long achunk = addr_to_chunk(base); unsigned long end_achunk = addr_to_chunk(base+size); if(_lmb->memory.region[i].type != LMB_MEMORY_AREA) continue; _lmb->memory.region[i].physbase = chunk_to_addr(pchunk); for (; achunk < end_achunk ;) { PTRRELOC(_msChunks->abs)[pchunk++] = achunk++; } }#ifdef CONFIG_MSCHUNKS /* Now create phys -> abs mapping for IO */ for (i=0; i < _lmb->memory.cnt ;i++) { unsigned long base = _lmb->memory.region[i].base; unsigned long size = _lmb->memory.region[i].size; unsigned long achunk = addr_to_chunk(base); unsigned long end_achunk = addr_to_chunk(base+size); if(_lmb->memory.region[i].type != LMB_IO_AREA) continue; _lmb->memory.region[i].physbase = chunk_to_addr(pchunk); for (; achunk < end_achunk ;) { PTRRELOC(_msChunks->abs)[pchunk++] = achunk++; } }#endif /* CONFIG_MSCHUNKS */ return mem;}#ifdef DEBUG_PROMvoidprom_dump_mschunks_mapping(void){ unsigned long offset = reloc_offset(); struct msChunks *_msChunks = PTRRELOC(&msChunks); unsigned long chunk; prom_print(RELOC("\nprom_dump_mschunks_mapping:\n")); prom_print(RELOC(" msChunks.num_chunks = 0x")); prom_print_hex(_msChunks->num_chunks); prom_print_nl(); prom_print(RELOC(" msChunks.chunk_size = 0x")); prom_print_hex(_msChunks->chunk_size); prom_print_nl(); prom_print(RELOC(" msChunks.chunk_shift = 0x")); prom_print_hex(_msChunks->chunk_shift); prom_print_nl(); prom_print(RELOC(" msChunks.chunk_mask = 0x")); prom_print_hex(_msChunks->chunk_mask); prom_print_nl(); prom_print(RELOC(" msChunks.abs = 0x")); prom_print_hex(_msChunks->abs); prom_print_nl(); prom_print(RELOC(" msChunks mapping:\n")); for(chunk=0; chunk < _msChunks->num_chunks ;chunk++) { prom_print(RELOC(" phys 0x")); prom_print_hex(chunk); prom_print(RELOC(" -> abs 0x")); prom_print_hex(PTRRELOC(_msChunks->abs)[chunk]); prom_print_nl(); }}#endif /* DEBUG_PROM */#endif /* CONFIG_MSCHUNKS */#ifdef DEBUG_PROMvoidprom_dump_lmb(void){ unsigned long i; unsigned long offset = reloc_offset(); struct lmb *_lmb = PTRRELOC(&lmb); prom_print(RELOC("\nprom_dump_lmb:\n")); prom_print(RELOC(" memory.cnt = 0x")); prom_print_hex(_lmb->memory.cnt); prom_print_nl(); prom_print(RELOC(" memory.size = 0x")); prom_print_hex(_lmb->memory.size); prom_print_nl(); prom_print(RELOC(" memory.lcd_size = 0x")); prom_print_hex(_lmb->memory.lcd_size); prom_print_nl(); for (i=0; i < _lmb->memory.cnt ;i++) { prom_print(RELOC(" memory.region[0x")); prom_print_hex(i); prom_print(RELOC("].base = 0x")); prom_print_hex(_lmb->memory.region[i].base); prom_print_nl(); prom_print(RELOC(" .physbase = 0x")); prom_print_hex(_lmb->memory.region[i].physbase); prom_print_nl(); prom_print(RELOC(" .size = 0x")); prom_print_hex(_lmb->memory.region[i].size); prom_print_nl(); prom_print(RELOC(" .type = 0x")); prom_print_hex(_lmb->memory.region[i].type); prom_print_nl(); } prom_print_nl(); prom_print(RELOC(" reserved.cnt = 0x")); prom_print_hex(_lmb->reserved.cnt); prom_print_nl(); prom_print(RELOC(" reserved.size = 0x")); prom_print_hex(_lmb->reserved.size); prom_print_nl(); prom_print(RELOC(" reserved.lcd_size = 0x")); prom_print_hex(_lmb->reserved.lcd_size); prom_print_nl(); for (i=0; i < _lmb->reserved.cnt ;i++) { prom_print(RELOC(" reserved.region[0x")); prom_print_hex(i); prom_print(RELOC("].base = 0x")); prom_print_hex(_lmb->reserved.region[i].base); prom_print_nl(); prom_print(RELOC(" .physbase = 0x")); prom_print_hex(_lmb->reserved.region[i].physbase); prom_print_nl(); prom_print(RELOC(" .size = 0x")); prom_print_hex(_lmb->reserved.region[i].size); prom_print_nl(); prom_print(RELOC(" .type = 0x")); prom_print_hex(_lmb->reserved.region[i].type); prom_print_nl(); }}#endif /* DEBUG_PROM */voidprom_initialize_tce_table(void){ phandle node; ihandle phb_node; unsigned long offset = reloc_offset(); char compatible[64], path[64], type[64], model[64]; unsigned long i, table = 0; unsigned long base, vbase, align; unsigned int minalign, minsize; struct _of_tce_table *prom_tce_table = RELOC(of_tce_table); unsigned long tce_entry, *tce_entryp;#ifdef DEBUG_PROM prom_print(RELOC("starting prom_initialize_tce_table\n"));#endif /* Search all nodes looking for PHBs. */ for (node = 0; prom_next_node(&node); ) { compatible[0] = 0; type[0] = 0; model[0] = 0; call_prom(RELOC("getprop"), 4, 1, node, RELOC("compatible"), compatible, sizeof(compatible)); call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"), type, sizeof(type)); call_prom(RELOC("getprop"), 4, 1, node, RELOC("model"), model, sizeof(model)); /* Keep the old logic in tack to avoid regression. */ if (compatible[0] != 0) { if((strstr(compatible, RELOC("python")) == NULL) && (strstr(compatible, RELOC("Speedwagon")) == NULL) && (strstr(compatible, RELOC("Winnipeg")) == NULL)) continue; } else if (model[0] != 0) { if ((strstr(model, RELOC("ython")) == NULL) && (strstr(model, RELOC("peedwagon")) == NULL) && (strstr(model, RELOC("innipeg")) == NULL)) continue; } else { prom_print(RELOC("No known I/O bridge chip found.\n")); } if ((type[0] == 0) || (strstr(type, RELOC("pci")) == NULL)) { continue; } if (call_prom(RELOC("getprop"), 4, 1, node, RELOC("tce-table-minalign"), &minalign, sizeof(minalign)) < 0) { minalign = 0; } if (call_prom(RELOC("getprop"), 4, 1, node, RELOC("tce-table-minsize"), &minsize, sizeof(minsize)) < 0) { minsize = 4UL << 20; } /* Even though we read what OF wants, we just set the table * size to 4 MB. This is enough to map 2GB of PCI DMA space. * By doing this, we avoid the pitfalls of trying to DMA to * MMIO space and the DMA alias hole. */ minsize = 4UL << 20; /* Align to the greater of the align or size */ align = (minalign < minsize) ? minsize : minalign; /* Carve out storage for the TCE table. */ base = lmb_alloc(minsize, align); if ( !base ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -