/* * Initialize PDC and related variables. */ void pdc_init() { int err; /* * Initialize important global variables (defined above). */ pdc = (pdcio_t)(u_long)PAGE0->mem_pdc; err = pdc_call(pdc, PDC_STABLE, PDC_STABLE_SIZE, pdcbuf, 0, 0); if (err >= 0) { sstorsiz = min(pdcbuf[0],sizeof(sstor)); err = (*pdc)(PDC_STABLE, PDC_STABLE_READ, 0, &sstor, sstorsiz); } /* * Now that we (may) have an output device, if we encountered * an error reading Stable Storage (above), let them know. */ #ifdef DEBUG if (debug && err) printf("Stable storage PDC_STABLE Read Ret'd %d\n", err); #endif /* * Clear the FAULT light (so we know when we get a real one) */ pdc_call(pdc, PDC_CHASSIS, PDC_CHASSIS_DISP, PDC_OSTAT(PDC_OSTAT_BOOT) | 0xCEC0); }
struct pdc_pat_pci_rt * pdc_getirt(int *pn) { struct pdc_pat_pci_rt *rt; int i, num, err; long cell; cell = -1; if (!pdc_call((iodcio_t)pdc, 0, PDC_PAT_CELL, PDC_PAT_CELL_GETID, &pdc_pat_cell_id, 0)) { cell = pdc_pat_cell_id.id; if ((err = pdc_call((iodcio_t)pdc, 0, PDC_PAT_IO, PDC_PAT_IO_GET_PCI_RTSZ, &pdc_pat_io_num, cell))) { printf("irt size error %d\n", err); return (NULL); } } else if ((err = pdc_call((iodcio_t)pdc, 0, PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL_SZ, &pdc_pat_io_num, cpu_gethpa(0)))) { printf("irt size error %d\n", err); return (NULL); } printf("num %ld ", pdc_pat_io_num.num); *pn = num = pdc_pat_io_num.num; if (num > sizeof(pdc_rt) / sizeof(*rt)) { printf("\nPCI IRT is too big %d\n", num); return (NULL); } if (!(rt = malloc(num * sizeof(*rt), M_DEVBUF, M_NOWAIT))) return (NULL); if (cell >= 0) { if ((err = pdc_call((iodcio_t)pdc, 0, PDC_PAT_IO, PDC_PAT_IO_GET_PCI_RT, rt, cell))) { printf("irt fetch error %d\n", err); free(rt, M_DEVBUF); return (NULL); } } else if ((err = pdc_call((iodcio_t)pdc, 0, PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL, &pdc_pat_io_num, cpu_gethpa(0), pdc_rt))) { printf("irt fetch error %d\n", err); free(rt, M_DEVBUF); return (NULL); } bcopy(pdc_rt, rt, num * sizeof(*rt)); for (i = 0; i < num; i++) printf("\n%d: ty 0x%02x it 0x%02x trig 0x%02x pin 0x%02x bus %d seg %d line %d addr 0x%llx", i, rt[i].type, rt[i].itype, rt[i].trigger, rt[i].pin, rt[i].bus, rt[i].seg, rt[i].line, rt[i].addr); return rt; }
void cpu_startup() { struct pdc_model pdc_model; register const struct hppa_board_info *bip; vm_offset_t minaddr, maxaddr; vm_size_t size; int base, residual; int err, i; #ifdef DEBUG extern int pmapdebug; int opmapdebug = pmapdebug; pmapdebug = 0; #endif /* good night */ printf(version); /* identify system type */ if ((err = pdc_call((iodcio_t)pdc, 0, PDC_MODEL, PDC_MODEL_INFO, &pdc_model)) < 0) { #ifdef DEBUG printf("WARNING: PDC_MODEL failed (%d)\n", err); #endif } else { i = pdc_model.hvers >> 4; /* board type */ for (bip = hppa_knownboards; bip->bi_id >= 0 && bip->bi_id != i; bip++); if (bip->bi_id >= 0) { char *p; switch(pdc_model.arch_rev) { case 0: p = "1.0"; break; case 4: p = "1.1"; break; case 8: p = "2.0"; break; default: p = "?.?"; break; } /* my babe said: 6010, 481, 0, 0, 77b657b1, 0, 4 */ sprintf(cpu_model, "HP9000/%s PA-RISC %s", bip->bi_name, p); } else sprintf(cpu_model, "HP9000/(UNKNOWN %x)", i); printf("%s\n", cpu_model); } printf("real mem = %d (%d reserved for PROM, %d used by OpenBSD)\n", ctob(totalphysmem), ctob(resvmem), ctob(physmem)); /* * Now allocate buffers proper. They are different than the above * in that they usually occupy more virtual memory than physical. */ size = MAXBSIZE * nbuf; buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers, &maxaddr, size, TRUE); minaddr = (vm_offset_t)buffers; if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0, &minaddr, size, FALSE) != KERN_SUCCESS) panic("cpu_startup: cannot allocate buffers"); base = bufpages / nbuf; residual = bufpages % nbuf; for (i = 0; i < nbuf; i++) { /* * First <residual> buffers get (base+1) physical pages * allocated for them. The rest get (base) physical pages. * * The rest of each buffer occupies virtual space, * but has no physical memory allocated for it. */ vm_map_pageable(buffer_map, minaddr, minaddr + CLBYTES * (base + (i < residual)), FALSE); vm_map_simplify(buffer_map, minaddr); minaddr += MAXBSIZE; } /* * Allocate a submap for exec arguments. This map effectively * limits the number of processes exec'ing at any time. */ exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, 16*NCARGS, TRUE); /* * Allocate a submap for physio */ phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, VM_PHYS_SIZE, TRUE); /* * Finally, allocate mbuf pool. Since mclrefcnt is an off-size * we use the more space efficient malloc in place of kmem_alloc. */ mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES, M_MBUF, M_NOWAIT); bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES); mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr, VM_MBUF_SIZE, FALSE); /* * Initialize callouts */ callfree = callout; for (i = 1; i < ncallout; i++) callout[i-1].c_next = &callout[i]; callout[i-1].c_next = NULL; #ifdef DEBUG pmapdebug = opmapdebug; #endif printf("avail mem = %ld\n", ptoa(cnt.v_free_count)); printf("using %d buffers containing %d bytes of memory\n", nbuf, bufpages * CLBYTES); /* * Set up buffers, so they can be used to read disk labels. */ bufinit(); /* * Configure the system. */ if (boothowto & RB_CONFIG) { #ifdef BOOT_CONFIG user_config(); #else printf("kernel does not support -c; continuing..\n"); #endif } hppa_malloc_ok = 1; configure(); }
void hppa_init() { extern int kernel_text, end; struct pdc_hwtlb pdc_hwtlb PDC_ALIGNMENT; struct pdc_coproc pdc_coproc PDC_ALIGNMENT; vm_offset_t v, vstart, vend; register int pdcerr; int usehpt; /* init PDC iface, so we can call em easy */ pdc_init(); /* calculate cpu speed */ cpu_hzticks = (PAGE0->mem_10msec * 100) / hz; delay_init(); /* * get cache parameters from the PDC */ if ((pdcerr = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_DFLT, &pdc_cache)) < 0) { #ifdef DIAGNOSTIC printf("Warning: PDC_CACHE call Ret'd %d\n", pdcerr); #endif } dcache_line_mask = pdc_cache.dc_conf.cc_line * 16 - 1; dcache_size = pdc_cache.dc_size; dcache_stride = pdc_cache.dc_stride; icache_stride = pdc_cache.ic_stride; /* * purge TLBs and flush caches */ if (pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, PDC_BTLB_PURGE_ALL) < 0) printf("WARNING: BTLB purge failed\n"); ptlball(); fcacheall(); /* calculate HPT size */ hpt_hashsize = PAGE0->imm_max_mem / NBPG; mtctl(hpt_hashsize - 1, CR_HPTMASK); /* * If we want to use the HW TLB support, ensure that it exists. */ if (pdc_call((iodcio_t)pdc, 0, PDC_TLB, PDC_TLB_INFO, &pdc_hwtlb) && !pdc_hwtlb.min_size && !pdc_hwtlb.max_size) { printf("WARNING: no HW tlb walker\n"); usehpt = 0; } else { usehpt = 1; #ifdef DEBUG printf("hwtlb: %u-%u, %u/", pdc_hwtlb.min_size, pdc_hwtlb.max_size, hpt_hashsize); #endif if (hpt_hashsize > pdc_hwtlb.max_size) hpt_hashsize = pdc_hwtlb.max_size; else if (hpt_hashsize < pdc_hwtlb.min_size) hpt_hashsize = pdc_hwtlb.min_size; #ifdef DEBUG printf("%u (0x%x)\n", hpt_hashsize, hpt_hashsize * sizeof(struct hpt_entry)); #endif } totalphysmem = PAGE0->imm_max_mem / NBPG; resvmem = ((vm_offset_t)&kernel_text) / NBPG; vstart = hppa_round_page(&end); vend = VM_MAX_KERNEL_ADDRESS; /* we hope this won't fail */ hppa_ex = extent_create("mem", 0x0, 0xffffffff, M_DEVBUF, (caddr_t)mem_ex_storage, sizeof(mem_ex_storage), EX_NOCOALESCE|EX_NOWAIT); if (extent_alloc_region(hppa_ex, 0, (vm_offset_t)PAGE0->imm_max_mem, EX_NOWAIT)) panic("cannot reserve main memory"); /* * Allocate space for system data structures. We are given * a starting virtual address and we return a final virtual * address; along the way we set each data structure pointer. * * We call allocsys() with 0 to find out how much space we want, * allocate that much and fill it with zeroes, and the call * allocsys() again with the correct base virtual address. */ v = vstart; #define valloc(name, type, num) \ (name) = (type *)v; v = (vm_offset_t)((name)+(num)) #ifdef REAL_CLISTS valloc(cfree, struct cblock, nclist); #endif valloc(callout, struct callout, ncallout); nswapmap = maxproc * 2; valloc(swapmap, struct map, nswapmap); #ifdef SYSVSHM valloc(shmsegs, struct shmid_ds, shminfo.shmmni); #endif #ifdef SYSVSEM valloc(sema, struct semid_ds, seminfo.semmni); valloc(sem, struct sem, seminfo.semmns); /* This is pretty disgusting! */ valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int)); #endif #ifdef SYSVMSG valloc(msgpool, char, msginfo.msgmax); valloc(msgmaps, struct msgmap, msginfo.msgseg); valloc(msghdrs, struct msg, msginfo.msgtql); valloc(msqids, struct msqid_ds, msginfo.msgmni); #endif #ifndef BUFCACHEPERCENT #define BUFCACHEPERCENT 10 #endif /* BUFCACHEPERCENT */ if (bufpages == 0) bufpages = totalphysmem / BUFCACHEPERCENT / CLSIZE; if (nbuf == 0) { nbuf = bufpages; if (nbuf < 16) nbuf = 16; } /* Restrict to at most 70% filled kvm */ if (nbuf * MAXBSIZE > (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) * 7 / 10) nbuf = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / MAXBSIZE * 7 / 10; /* More buffer pages than fits into the buffers is senseless. */ if (bufpages > nbuf * MAXBSIZE / CLBYTES) bufpages = nbuf * MAXBSIZE / CLBYTES; if (nswbuf == 0) { nswbuf = (nbuf / 2) & ~1; /* force even */ if (nswbuf > 256) nswbuf = 256; /* sanity */ } valloc(swbuf, struct buf, nswbuf); valloc(buf, struct buf, nbuf); #undef valloc bzero ((void *)vstart, (v - vstart)); vstart = v; pmap_bootstrap(&vstart, &vend); physmem = totalphysmem - btoc(vstart); /* alloc msgbuf */ if (!(msgbufp = (void *)pmap_steal_memory(sizeof(struct msgbuf), NULL, NULL))) panic("cannot allocate msgbuf"); msgbufmapped = 1; #ifdef DEBUG printf("mem: %x+%x, %x\n", physmem, resvmem, totalphysmem); #endif /* Turn on the HW TLB assist */ if (usehpt) { if ((pdcerr = pdc_call((iodcio_t)pdc, 0, PDC_TLB, PDC_TLB_CONFIG, &pdc_hwtlb, hpt_table, sizeof(struct hpt_entry) * hpt_hashsize, PDC_TLB_WORD3)) < 0) { printf("Warning: HW TLB init failed (%d), disabled\n", pdcerr); usehpt = 0; } else printf("HW TLB(%d entries at 0x%x) initialized (%d)\n", hpt_hashsize, hpt_table, pdcerr); } /* * Locate any coprocessors and enable them by setting up the CCR. * SFU's are ignored (since we dont have any). Also, initialize * the floating point registers here. */ if ((pdcerr = pdc_call((iodcio_t)pdc, 0, PDC_COPROC, PDC_COPROC_DFLT, &pdc_coproc)) < 0) printf("WARNING: PDC_COPROC call Ret'd %d\n", pdcerr); else { #ifdef DEBUG printf("pdc_coproc: %x, %x\n", pdc_coproc.ccr_enable, pdc_coproc.ccr_present); #endif } copr_sfu_config = pdc_coproc.ccr_enable; mtctl(copr_sfu_config & CCR_MASK, CR_CCR); /* fprinit(&fpcopr_version); fpcopr_version = (fpcopr_version & 0x003ff800) >> 11; mtctl(CR_CCR, 0); */ /* * Clear the FAULT light (so we know when we get a real one) * PDC_COPROC apparently turns it on (for whatever reason). */ pdcerr = PDC_OSTAT(PDC_OSTAT_RUN) | 0xCEC0; (void) (*pdc)(PDC_CHASSIS, PDC_CHASSIS_DISP, pdcerr); #ifdef DDB ddb_init(); #endif #ifdef DEBUG printf("hppa_init: leaving\n"); #endif kernelmapped++; }
void memattach(struct device *parent, struct device *self, void *aux) { struct pdc_iodc_minit pdc_minit PDC_ALIGNMENT; struct confargs *ca = aux; struct mem_softc *sc = (struct mem_softc *)self; int s, err, pagezero_cookie; char bits[128]; printf (":"); pagezero_cookie = hp700_pagezero_map(); /* XXX check if we are dealing w/ Viper */ if (ca->ca_hpa == (hppa_hpa_t)VIPER_HPA) { sc->sc_vp = (struct vi_trs *) &((struct iomod *)ca->ca_hpa)->priv_trs; /* XXX other values seem to blow it up */ if (sc->sc_vp->vi_status.hw_rev == 0) { bitmask_snprintf(VI_CTRL, VIPER_BITS, bits, sizeof(bits)); printf (" viper rev %x, ctrl %s", sc->sc_vp->vi_status.hw_rev, bits); s = splhigh(); VI_CTRL |= VI_CTRL_ANYDEN; ((struct vi_ctrl *)&VI_CTRL)->core_den = 0; ((struct vi_ctrl *)&VI_CTRL)->sgc0_den = 0; ((struct vi_ctrl *)&VI_CTRL)->sgc1_den = 0; ((struct vi_ctrl *)&VI_CTRL)->core_prf = 1; sc->sc_vp->vi_control = VI_CTRL; splx(s); #ifdef DEBUG bitmask_snprintf(VI_CTRL, VIPER_BITS, bits, sizeof(bits)); printf (" >> %s", bits); #endif } else sc->sc_vp = NULL; } else sc->sc_vp = NULL; if ((err = pdc_call((iodcio_t)pdc, 0, PDC_IODC, PDC_IODC_NINIT, &pdc_minit, ca->ca_hpa, PAGE0->imm_spa_size)) < 0) pdc_minit.max_spa = PAGE0->imm_max_mem; hp700_pagezero_unmap(pagezero_cookie); printf (" size %d", pdc_minit.max_spa / (1024*1024)); if (pdc_minit.max_spa % (1024*1024)) printf (".%d", pdc_minit.max_spa % (1024*1024)); printf ("MB"); /* L2 cache controller is a part of the memory controller on PCXL2 */ if (HPPA_PA_SPEC_MAJOR(hppa_cpu_info->hppa_cpu_info_pa_spec) == 1 && HPPA_PA_SPEC_MINOR(hppa_cpu_info->hppa_cpu_info_pa_spec) == 1 && HPPA_PA_SPEC_LETTER(hppa_cpu_info->hppa_cpu_info_pa_spec) == 'e') { sc->sc_l2 = (struct l2_mioc *)ca->ca_hpa; #ifdef DEBUG bitmask_snprintf(sc->sc_l2->sltcv, SLTCV_BITS, bits, sizeof(bits)); printf(", sltcv %s", bits); #endif /* sc->sc_l2->sltcv |= SLTCV_UP4COUT; */ if (sc->sc_l2->sltcv & SLTCV_ENABLE) { uint32_t tagmask = sc->sc_l2->tagmask >> 20; printf(", %dMB L2 cache", tagmask + 1); }
void pdc_scan(struct device *self, struct confargs *ca) { struct device_path path; struct confargs nca; u_long rv[16]; int i, err, mod = ca->ca_mod; if (pdc_call((iodcio_t)pdc, 0, PDC_PAT_CELL, PDC_PAT_CELL_GETID, &pdc_pat_cell_id, 0)) for (i = 0; !(err = pdc_call((iodcio_t)pdc, 0, PDC_SYSMAP, PDC_SYSMAP_FIND, &pdc_find, &path, i)); i++) { if (autoconf_verbose) printf(">> hpa %x/%x dp %d/%d/%d/%d/%d/%d.%d\n", pdc_find.hpa, pdc_find.size, path.dp_bc[0], path.dp_bc[1], path.dp_bc[2], path.dp_bc[3], path.dp_bc[4], path.dp_bc[5], path.dp_mod); if (path.dp_bc[5] == mod) { nca = *ca; nca.ca_name = NULL; nca.ca_hpa = 0xffffffff00000000ULL | (hppa_hpa_t)pdc_find.hpa; nca.ca_hpasz = pdc_find.size; nca.ca_mod = path.dp_mod; err = pdc_call((iodcio_t)pdc, 0, PDC_IODC, PDC_IODC_READ, &pdc_iodc_read, nca.ca_hpa, IODC_DATA, &nca.ca_type, sizeof(nca.ca_type)); if (err < 0 || pdc_iodc_read.size < 8) { if (autoconf_verbose) printf(">> iodc_data error %d\n", err); bzero(&nca.ca_type, sizeof(nca.ca_type)); } if (autoconf_verbose) { u_int *p = (u_int *)&nca.ca_type; printf(">> iodc_data 0x%08x 0x%08x\n", p[0], p[1]); } config_found(self, &nca, mbprint); } } for (i = 0; !(err = pdc_call((iodcio_t)pdc, 0, PDC_PAT_CELL, PDC_PAT_CELL_MODULE, rv, pdc_pat_cell_id.loc, i, PDC_PAT_PAVIEW, &pdc_pat_cell_module, 0)); i++) { if (autoconf_verbose) printf(">> chpa %lx info %lx loc %lx " "dp %d/%d/%d/%d/%d/%d.%d\n", pdc_pat_cell_module.chpa, pdc_pat_cell_module.info, pdc_pat_cell_module.loc, pdc_pat_cell_module.dp.dp_bc[0], pdc_pat_cell_module.dp.dp_bc[1], pdc_pat_cell_module.dp.dp_bc[2], pdc_pat_cell_module.dp.dp_bc[3], pdc_pat_cell_module.dp.dp_bc[4], pdc_pat_cell_module.dp.dp_bc[5], pdc_pat_cell_module.dp.dp_mod); if (pdc_pat_cell_module.dp.dp_bc[5] == mod) { int t; t = PDC_PAT_CELL_MODTYPE(pdc_pat_cell_module.info); if (t >= sizeof(pat_names)/sizeof(pat_names[0])) continue; nca = *ca; nca.ca_name = pat_names[t]; nca.ca_hpa = pdc_pat_cell_module.chpa & ~(u_long)PAGE_MASK; nca.ca_hpasz = PDC_PAT_CELL_MODSIZE(pdc_pat_cell_module.info); nca.ca_mod = pdc_pat_cell_module.dp.dp_mod; err = pdc_call((iodcio_t)pdc, 0, PDC_IODC, PDC_IODC_READ, &pdc_iodc_read, nca.ca_hpa, IODC_DATA, &nca.ca_type, sizeof(nca.ca_type)); if (err < 0 || pdc_iodc_read.size < 8) { if (autoconf_verbose) printf(">> iodc_data error %d\n", err); bzero(&nca.ca_type, sizeof(nca.ca_type)); } if (autoconf_verbose) { u_int *p = (u_int *)&nca.ca_type; printf(">> iodc_data 0x%08x 0x%08x\n", p[0], p[1]); } config_found(self, &nca, mbprint); } } }