/* Main entry points */ static int dummy_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int flags, char *name, caddr_t valuep, int *lengthp) { cmn_err(CE_NOTE, "Inside dummy_prop_op"); return(ddi_prop_op(dev,dip,prop_op,flags,name,valuep,lengthp)); }
static int pci_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int flags, char *name, caddr_t valuep, int *lengthp) { if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "hotplug-capable")) return ((pcihp_get_cb_ops())->cb_prop_op(dev, dip, prop_op, flags, name, valuep, lengthp)); return (ddi_prop_op(dev, dip, prop_op, flags, name, valuep, lengthp)); }
/* * If the device is a PCI bus device (i.e bus-range property exists) then * claim the bus numbers used by the device from the specified bus * resource map. */ static int claim_pci_busnum(dev_info_t *dip, void *arg) { struct bus_range pci_bus_range; struct busnum_ctrl *ctrl; ndi_ra_request_t req; char bus_type[16] = "(unknown)"; int len; uint64_t base; uint64_t retlen; ctrl = (struct busnum_ctrl *)arg; /* check if this is a PCI bus node */ len = sizeof (bus_type); if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "device_type", (caddr_t)&bus_type, &len) != DDI_SUCCESS) return (DDI_WALK_PRUNECHILD); /* it is not a pci/pci-ex bus type */ if ((strcmp(bus_type, "pci") != 0) && (strcmp(bus_type, "pciex") != 0)) return (DDI_WALK_PRUNECHILD); /* look for the bus-range property */ len = sizeof (struct bus_range); if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "bus-range", (caddr_t)&pci_bus_range, &len) == DDI_SUCCESS) { if ((pci_bus_range.lo >= ctrl->range->lo) && (pci_bus_range.hi <= ctrl->range->hi)) { /* claim the bus range from the bus resource map */ bzero((caddr_t)&req, sizeof (req)); req.ra_addr = (uint64_t)pci_bus_range.lo; req.ra_flags |= NDI_RA_ALLOC_SPECIFIED; req.ra_len = (uint64_t)pci_bus_range.hi - (uint64_t)pci_bus_range.lo + 1; if (ndi_ra_alloc(ctrl->dip, &req, &base, &retlen, NDI_RA_TYPE_PCI_BUSNUM, 0) == NDI_SUCCESS) return (DDI_WALK_PRUNECHILD); } } /* * Error return. */ ctrl->rv = DDI_FAILURE; return (DDI_WALK_TERMINATE); }
int get_portid_ddi(dev_info_t *dip, dev_info_t **cmpp) { int portid; int i; char dev_type[OBP_MAXPROPNAME]; int len = OBP_MAXPROPNAME; dev_info_t *cpu_parent; if (cmpp != NULL) *cmpp = NULL; if ((portid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "portid", -1)) != -1) return (portid); if ((portid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "upa-portid", -1)) != -1) return (portid); if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, DDI_PROP_DONTPASS, "device_type", (caddr_t)dev_type, &len) != 0) return (-1); /* * For a virtual cpu node that is a CMP core, the "portid" * is in the parent node. * For a virtual cpu node that is a CMT strand, the "portid" is * in its grandparent node. * So we iterate up as far as 2 levels to get the "portid". */ if (strcmp(dev_type, "cpu") == 0) { cpu_parent = dip = ddi_get_parent(dip); for (i = 0; dip != NULL && i < 2; i++) { if ((portid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "portid", -1)) != -1) { if (cmpp != NULL) *cmpp = cpu_parent; return (portid); } dip = ddi_get_parent(dip); } } return (-1); }
/* * A hotplug version of fill_cpu(). (Doesn't assume that there's a node * in the PROM device tree for this CPU.) We still need the PROM version * since it is called very early in the boot cycle before (before * setup_ddi()). Sigh...someday this will all be cleaned up. */ void fill_cpu_ddi(dev_info_t *dip) { extern int cpu_get_cpu_unum(int, char *, int, int *); struct cpu_node *cpunode; processorid_t cpuid; int portid; int len = OBP_MAXPROPNAME; int tlbsize; dev_info_t *cmpnode; char namebuf[OBP_MAXPROPNAME], unum[UNUM_NAMLEN]; char *namebufp; char dev_type[OBP_MAXPROPNAME]; if ((portid = get_portid_ddi(dip, &cmpnode)) == -1) { cmn_err(CE_PANIC, "portid not found"); } if ((cpuid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "cpuid", -1)) == -1) { cpuid = portid; } if (cpuid < 0 || cpuid >= NCPU) { cmn_err(CE_PANIC, "cpu dip %p: cpuid %d out of range", (void *)dip, cpuid); return; } cpunode = &cpunodes[cpuid]; cpunode->portid = portid; cpunode->nodeid = ddi_get_nodeid(dip); if (cmpnode != NULL) { /* * For the CMT case, the parent "core" node contains * properties needed below, use it instead of the * cpu node. */ if ((ddi_prop_op(DDI_DEV_T_ANY, cmpnode, PROP_LEN_AND_VAL_BUF, DDI_PROP_DONTPASS, "device_type", (caddr_t)dev_type, &len) == DDI_PROP_SUCCESS) && (strcmp(dev_type, "core") == 0)) dip = cmpnode; } if (cpu_get_cpu_unum(cpuid, unum, UNUM_NAMLEN, &len) != 0) { cpunode->fru_fmri[0] = '\0'; } else { (void) snprintf(cpunode->fru_fmri, sizeof (cpunode->fru_fmri), "%s%s", CPU_FRU_FMRI, unum); } len = sizeof (namebuf); (void) ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, DDI_PROP_DONTPASS, (cmpnode ? "compatible" : "name"), (caddr_t)namebuf, &len); namebufp = namebuf; if (strncmp(namebufp, "SUNW,", 5) == 0) namebufp += 5; else if (strncmp(namebufp, "FJSV,", 5) == 0) namebufp += 5; (void) strcpy(cpunode->name, namebufp); cpunode->implementation = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "implementation#", 0); cpunode->version = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "mask#", 0); if (IS_CHEETAH(cpunode->implementation)) { /* remap mask reg */ cpunode->version = REMAP_CHEETAH_MASK(cpunode->version); } cpunode->clock_freq = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "clock-frequency", 0); ASSERT(cpunode->clock_freq != 0); /* * Compute scaling factor based on rate of %tick. This is used * to convert from ticks derived from %tick to nanoseconds. See * comment in sun4u/sys/clock.h for details. */ cpunode->tick_nsec_scale = (uint_t)(((uint64_t)NANOSEC << (32 - TICK_NSEC_SHIFT)) / cpunode->clock_freq); tlbsize = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "#itlb-entries", 0); ASSERT(tlbsize < USHRT_MAX); /* since we cast it */ cpunode->itlb_size = (ushort_t)tlbsize; tlbsize = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "#dtlb-entries", 0); ASSERT(tlbsize < USHRT_MAX); /* since we cast it */ cpunode->dtlb_size = (ushort_t)tlbsize; if (cmpnode != NULL) { /* * If the CPU has a level 3 cache, then that is it's * external cache. Otherwise the external cache must * be the level 2 cache. */ cpunode->ecache_size = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "l3-cache-size", 0); if (cpunode->ecache_size == 0) cpunode->ecache_size = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "l2-cache-size", 0); ASSERT(cpunode->ecache_size != 0); cpunode->ecache_linesize = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "l3-cache-line-size", 0); if (cpunode->ecache_linesize == 0) cpunode->ecache_linesize = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "l2-cache-line-size", 0); ASSERT(cpunode->ecache_linesize != 0); cpunode->ecache_associativity = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "l2-cache-associativity", 0); ASSERT(cpunode->ecache_associativity != 0); cmp_add_cpu(portid, cpuid); } else { cpunode->ecache_size = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "ecache-size", 0); ASSERT(cpunode->ecache_size != 0); cpunode->ecache_linesize = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "ecache-line-size", 0); ASSERT(cpunode->ecache_linesize != 0); cpunode->ecache_associativity = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "ecache-associativity", 0); ASSERT(cpunode->ecache_associativity != 0); } /* by default set msram to non-mirrored one */ cpunode->msram = ECACHE_CPU_NON_MIRROR; if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "msram")) { cpunode->msram = ECACHE_CPU_MIRROR; } else if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "msram-observed")) { cpunode->msram = ECACHE_CPU_MIRROR; } ASSERT(ncpunode > 0); /* fiximp not req'd */ cpunode->ecache_setsize = cpunode->ecache_size / cpunode->ecache_associativity; adj_ecache_setsize(cpunode->ecache_setsize); ncpunode++; }
static int logiinit(dev_info_t *dip) { int i; int ioaddr; int len; int old_probe; #ifdef LOGI_DEBUG if (logi_debug) PRF("logiinit: call BASE_IOA = %x\n", BASE_IOA); #endif old_probe = ddi_getprop(DDI_DEV_T_ANY, dip, 0, "ignore-hardware-nodes", 0); if (old_probe) { len = sizeof (int); /* * check if ioaddr is set in .conf file, it should be. If it * isn't then try the default i/o addr */ if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, DDI_PROP_DONTPASS, "ioaddr", (caddr_t)&ioaddr, &len) == DDI_PROP_SUCCESS) BASE_IOA = ioaddr; } else { int reglen, nregs; int i; struct { int bustype; int base; int size; } *reglist; /* new probe */ if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg", (caddr_t)®list, ®len) != DDI_PROP_SUCCESS) return (DDI_PROBE_FAILURE); nregs = reglen / sizeof (*reglist); for (i = 0; i < nregs; i++) if (reglist[i].bustype == 1) { ioaddr = reglist[i].base; BASE_IOA = ioaddr; break; } kmem_free(reglist, reglen); } #ifdef LOGI_DEBUG if (logi_debug) PRF("logiinit: call BASE_IOA = %x\n", BASE_IOA); #endif mse_config.present = 0; /* Check if the mouse board exists */ outb(CONFIGURATOR_PORT, 0x91); drv_usecwait(10); outb(SIGNATURE_PORT, 0xC); drv_usecwait(10); i = inb(SIGNATURE_PORT); drv_usecwait(10); outb(SIGNATURE_PORT, 0x50); drv_usecwait(10); if (i == 0xC && ((inb(SIGNATURE_PORT)) == 0x50)) { mse_config.present = 1; #ifdef LOGI_DEBUG if (logi_debug) printf("logiinit:Disable interrupts ioaddr %x\n", BASE_IOA); #endif control_port(INTR_DISABLE); /* Disable interrupts */ #ifdef LOGI_DEBUG if (logi_debug) PRF("logiinit: succeeded\n"); #endif return (DDI_SUCCESS); } else { #ifdef LOGI_DEBUG if (logi_debug) PRF("logiinit: failed\n"); #endif return (DDI_PROBE_FAILURE); } }
/* * Setup resource map for the pci bus node based on the "available" * property and "bus-range" property. */ int pci_resource_setup(dev_info_t *dip) { pci_regspec_t *regs; int rlen, rcount, i; char bus_type[16] = "(unknown)"; int len; struct busnum_ctrl ctrl; int circular_count; int rval = NDI_SUCCESS; /* * If this is a pci bus node then look for "available" property * to find the available resources on this bus. */ len = sizeof (bus_type); if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "device_type", (caddr_t)&bus_type, &len) != DDI_SUCCESS) return (NDI_FAILURE); /* it is not a pci/pci-ex bus type */ if ((strcmp(bus_type, "pci") != 0) && (strcmp(bus_type, "pciex") != 0)) return (NDI_FAILURE); /* * The pci-hotplug project addresses adding the call * to pci_resource_setup from pci nexus driver. * However that project would initially be only for x86, * so for sparc pcmcia-pci support we still need to call * pci_resource_setup in pcic driver. Once all pci nexus drivers * are updated to call pci_resource_setup this portion of the * code would really become an assert to make sure this * function is not called for the same dip twice. */ { if (ra_map_exist(dip, NDI_RA_TYPE_MEM) == NDI_SUCCESS) { return (NDI_FAILURE); } } /* * Create empty resource maps first. * * NOTE: If all the allocated resources are already assigned to * device(s) in the hot plug slot then "available" property may not * be present. But, subsequent hot plug operation may unconfigure * the device in the slot and try to free up it's resources. So, * at the minimum we should create empty maps here. */ if (ndi_ra_map_setup(dip, NDI_RA_TYPE_MEM) == NDI_FAILURE) { return (NDI_FAILURE); } if (ndi_ra_map_setup(dip, NDI_RA_TYPE_IO) == NDI_FAILURE) { return (NDI_FAILURE); } if (ndi_ra_map_setup(dip, NDI_RA_TYPE_PCI_BUSNUM) == NDI_FAILURE) { return (NDI_FAILURE); } if (ndi_ra_map_setup(dip, NDI_RA_TYPE_PCI_PREFETCH_MEM) == NDI_FAILURE) { return (NDI_FAILURE); } /* read the "available" property if it is available */ if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "available", (caddr_t)®s, &rlen) == DDI_SUCCESS) { /* * create the available resource list for both memory and * io space */ rcount = rlen / sizeof (pci_regspec_t); for (i = 0; i < rcount; i++) { switch (PCI_REG_ADDR_G(regs[i].pci_phys_hi)) { case PCI_REG_ADDR_G(PCI_ADDR_MEM32): (void) ndi_ra_free(dip, (uint64_t)regs[i].pci_phys_low, (uint64_t)regs[i].pci_size_low, (regs[i].pci_phys_hi & PCI_REG_PF_M) ? NDI_RA_TYPE_PCI_PREFETCH_MEM : NDI_RA_TYPE_MEM, 0); break; case PCI_REG_ADDR_G(PCI_ADDR_MEM64): (void) ndi_ra_free(dip, ((uint64_t)(regs[i].pci_phys_mid) << 32) | ((uint64_t)(regs[i].pci_phys_low)), ((uint64_t)(regs[i].pci_size_hi) << 32) | ((uint64_t)(regs[i].pci_size_low)), (regs[i].pci_phys_hi & PCI_REG_PF_M) ? NDI_RA_TYPE_PCI_PREFETCH_MEM : NDI_RA_TYPE_MEM, 0); break; case PCI_REG_ADDR_G(PCI_ADDR_IO): (void) ndi_ra_free(dip, (uint64_t)regs[i].pci_phys_low, (uint64_t)regs[i].pci_size_low, NDI_RA_TYPE_IO, 0); break; case PCI_REG_ADDR_G(PCI_ADDR_CONFIG): break; default: cmn_err(CE_WARN, "pci_resource_setup: bad addr type: %x\n", PCI_REG_ADDR_G(regs[i].pci_phys_hi)); break; } } kmem_free((caddr_t)regs, rlen); } /* * update resource map for available bus numbers if the node * has available-bus-range or bus-range property. */ len = sizeof (struct bus_range); if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "available-bus-range", (caddr_t)&pci_bus_range, &len) == DDI_SUCCESS) { /* * Add bus numbers in the range to the free list. */ (void) ndi_ra_free(dip, (uint64_t)pci_bus_range.lo, (uint64_t)pci_bus_range.hi - (uint64_t)pci_bus_range.lo + 1, NDI_RA_TYPE_PCI_BUSNUM, 0); } else { /* * We don't have an available-bus-range property. If, instead, * we have a bus-range property we add all the bus numbers * in that range to the free list but we must then scan * for pci-pci bridges on this bus to find out the if there * are any of those bus numbers already in use. If so, we can * reclaim them. */ len = sizeof (struct bus_range); if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "bus-range", (caddr_t)&pci_bus_range, &len) == DDI_SUCCESS) { if (pci_bus_range.lo != pci_bus_range.hi) { /* * Add bus numbers other than the secondary * bus number to the free list. */ (void) ndi_ra_free(dip, (uint64_t)pci_bus_range.lo + 1, (uint64_t)pci_bus_range.hi - (uint64_t)pci_bus_range.lo, NDI_RA_TYPE_PCI_BUSNUM, 0); /* scan for pci-pci bridges */ ctrl.rv = DDI_SUCCESS; ctrl.dip = dip; ctrl.range = &pci_bus_range; ndi_devi_enter(dip, &circular_count); ddi_walk_devs(ddi_get_child(dip), claim_pci_busnum, (void *)&ctrl); ndi_devi_exit(dip, circular_count); if (ctrl.rv != DDI_SUCCESS) { /* failed to create the map */ (void) ndi_ra_map_destroy(dip, NDI_RA_TYPE_PCI_BUSNUM); rval = NDI_FAILURE; } } } } #ifdef BUSRA_DEBUG if (busra_debug) { (void) ra_dump_all(NULL, dip); } #endif return (rval); }