int magma_match(device_t parent, cfdata_t cf, void *aux) { struct sbus_attach_args *sa = aux; struct magma_board_info *card; /* See if we support this device */ for (card = supported_cards; ; card++) { if (card->mb_sbusname == NULL) /* End of table: no match */ return (0); if (strcmp(sa->sa_name, card->mb_sbusname) == 0) break; } dprintf(("magma: matched `%s'\n", sa->sa_name)); dprintf(("magma: magma_prom `%s'\n", prom_getpropstring(sa->sa_node, "magma_prom"))); dprintf(("magma: intlevels `%s'\n", prom_getpropstring(sa->sa_node, "intlevels"))); dprintf(("magma: chiprev `%s'\n", prom_getpropstring(sa->sa_node, "chiprev"))); dprintf(("magma: clock `%s'\n", prom_getpropstring(sa->sa_node, "clock"))); return (1); }
/* * Get the number of CPUs in the system and the CPUs' SPARC architecture * version. We need this information early in the boot process. */ int find_cpus(void) { int n; #if defined(SUN4M) || defined(SUN4D) int node; #endif /* * Set default processor architecture version * * All sun4 and sun4c platforms have v7 CPUs; * sun4m may have v7 (Cyrus CY7C601 modules) or v8 CPUs (all * other models, presumably). */ cpu_arch = 7; /* On sun4 and sun4c we support only one CPU */ if (!CPU_ISSUN4M && !CPU_ISSUN4D) return (1); n = 0; #if defined(SUN4M) node = findroot(); for (node = firstchild(node); node; node = nextsibling(node)) { if (strcmp(prom_getpropstring(node, "device_type"), "cpu") != 0) continue; if (n++ == 0) cpu_arch = prom_getpropint(node, "sparc-version", 7); } #endif /* SUN4M */ #if defined(SUN4D) node = findroot(); for (node = firstchild(node); node; node = nextsibling(node)) { int unode; if (strcmp(prom_getpropstring(node, "name"), "cpu-unit") != 0) continue; for (unode = firstchild(node); unode; unode = nextsibling(unode)) { if (strcmp(prom_getpropstring(unode, "device_type"), "cpu") != 0) continue; if (n++ == 0) cpu_arch = prom_getpropint(unode, "sparc-version", 7); } } #endif return (n); }
/* * Match a struct device against the bootpath, by * comparing it's firmware package handle and calculating * the target/lun suffix and comparing that against * the bootpath remainder. */ static void dev_path_drive_match(struct device *dev, int ctrlnode, int target, int lun) { int child = 0; char buf[OFPATHLEN]; DPRINTF(ACDB_BOOTDEV, ("dev_path_drive_match: %s, controller %x, " "target %d lun %d\n", device_xname(dev), ctrlnode, target, lun)); /* * The ofbootpackage points to a disk on this controller, so * iterate over all child nodes and compare. */ for (child = prom_firstchild(ctrlnode); child != 0; child = prom_nextsibling(child)) if (child == ofbootpackage) break; if (child == ofbootpackage) { /* boot device is on this controller */ DPRINTF(ACDB_BOOTDEV, ("found controller of bootdevice\n")); sprintf(buf, "%s@%d,%d", prom_getpropstring(child, "name"), target, lun); if (ofboottarget && strcmp(buf, ofboottarget) == 0) { booted_device = dev; if (ofbootpartition) booted_partition = *ofbootpartition - 'a'; DPRINTF(ACDB_BOOTDEV, ("found boot device: %s" ", partition %d\n", device_xname(dev), booted_partition)); } } }
static int psycho_match(device_t parent, cfdata_t match, void *aux) { struct mainbus_attach_args *ma = aux; char *model = prom_getpropstring(ma->ma_node, "model"); int i; /* match on a name of "pci" and a sabre or a psycho */ if (strcmp(ma->ma_name, ROM_PCI_NAME) == 0) { for (i=0; psycho_names[i].p_name; i++) if (strcmp(model, psycho_names[i].p_name) == 0) return (1); model = prom_getpropstring(ma->ma_node, "compatible"); for (i=0; psycho_names[i].p_name; i++) if (strcmp(model, psycho_names[i].p_name) == 0) return (1); } return (0); }
/* * Match a graphics device. */ static int genfb_match_sbus(device_t parent, cfdata_t cf, void *aux) { struct sbus_attach_args *sa = aux; /* if there's no address property we can't use the device */ if (prom_getpropint(sa->sa_node, "address", -1) == -1) return 0; if (strcmp("display", prom_getpropstring(sa->sa_node, "device_type")) == 0) return 1; return 0; }
int sab_match(struct device *parent, struct cfdata *match, void *aux) { struct ebus_attach_args *ea = aux; char *compat; if (strcmp(ea->ea_name, "se") == 0) return (1); compat = prom_getpropstring(ea->ea_node, "compatible"); if (compat != NULL && !strcmp(compat, "sab82532")) return (1); return (0); }
/* * Match a device_t against the bootpath, by * comparing it's firmware package handle and calculating * the target/lun suffix and comparing that against * the bootpath remainder. */ static void dev_path_drive_match(device_t dev, int ctrlnode, int target, uint64_t wwn, int lun) { int child = 0; char buf[OFPATHLEN]; DPRINTF(ACDB_BOOTDEV, ("dev_path_drive_match: %s, controller %x, " "target %d wwn %016" PRIx64 " lun %d\n", device_xname(dev), ctrlnode, target, wwn, lun)); /* * The ofbootpackage points to a disk on this controller, so * iterate over all child nodes and compare. */ for (child = prom_firstchild(ctrlnode); child != 0; child = prom_nextsibling(child)) if (child == ofbootpackage) break; if (child == ofbootpackage) { const char * name = prom_getpropstring(child, "name"); /* boot device is on this controller */ DPRINTF(ACDB_BOOTDEV, ("found controller of bootdevice\n")); /* * Note: "child" here is == ofbootpackage (s.a.), which * may be completely wrong for the device we are checking, * what we realy do here is to match "target" and "lun". */ if (wwn) sprintf(buf, "%s@w%016" PRIx64 ",%d", name, wwn, lun); else sprintf(buf, "%s@%d,%d", name, target, lun); if (ofboottarget && strcmp(buf, ofboottarget) == 0) { booted_device = dev; if (ofbootpartition) booted_partition = *ofbootpartition - 'a'; DPRINTF(ACDB_BOOTDEV, ("found boot device: %s" ", partition %d\n", device_xname(dev), booted_partition)); } } }
/* * Attach the CPU. * Discover interesting goop about the virtual address cache * (slightly funny place to do it, but this is where it is to be found). */ void cpu_attach(device_t parent, device_t dev, void *aux) { int node; long clk, sclk = 0; struct mainbus_attach_args *ma = aux; struct cpu_info *ci; const char *sep; register int i, l; int bigcache, cachesize; char buf[100]; int totalsize = 0; int linesize, dcachesize, icachesize; /* tell them what we have */ node = ma->ma_node; /* * Allocate cpu_info structure if needed. */ ci = alloc_cpuinfo((u_int)node); /* * Only do this on the boot cpu. Other cpu's call * cpu_reset_fpustate() from cpu_hatch() before they * call into the idle loop. * For other cpus, we need to call mi_cpu_attach() * and complete setting up cpcb. */ if (ci->ci_flags & CPUF_PRIMARY) { fpstate_cache = pool_cache_init(sizeof(struct fpstate64), SPARC64_BLOCK_SIZE, 0, 0, "fpstate", NULL, IPL_NONE, NULL, NULL, NULL); cpu_reset_fpustate(); } #ifdef MULTIPROCESSOR else { mi_cpu_attach(ci); ci->ci_cpcb = lwp_getpcb(ci->ci_data.cpu_idlelwp); } for (i = 0; i < IPI_EVCNT_NUM; ++i) evcnt_attach_dynamic(&ci->ci_ipi_evcnt[i], EVCNT_TYPE_INTR, NULL, device_xname(dev), ipi_evcnt_names[i]); #endif evcnt_attach_dynamic(&ci->ci_tick_evcnt, EVCNT_TYPE_INTR, NULL, device_xname(dev), "timer"); mutex_init(&ci->ci_ctx_lock, MUTEX_SPIN, IPL_VM); clk = prom_getpropint(node, "clock-frequency", 0); if (clk == 0) { /* * Try to find it in the OpenPROM root... */ clk = prom_getpropint(findroot(), "clock-frequency", 0); } if (clk) { /* Tell OS what frequency we run on */ ci->ci_cpu_clockrate[0] = clk; ci->ci_cpu_clockrate[1] = clk / 1000000; } sclk = prom_getpropint(findroot(), "stick-frequency", 0); ci->ci_system_clockrate[0] = sclk; ci->ci_system_clockrate[1] = sclk / 1000000; snprintf(buf, sizeof buf, "%s @ %s MHz", prom_getpropstring(node, "name"), clockfreq(clk)); snprintf(cpu_model, sizeof cpu_model, "%s (%s)", machine_model, buf); aprint_normal(": %s, UPA id %d\n", buf, ci->ci_cpuid); aprint_naive("\n"); if (ci->ci_system_clockrate[0] != 0) { aprint_normal_dev(dev, "system tick frequency %d MHz\n", (int)ci->ci_system_clockrate[1]); } aprint_normal_dev(dev, ""); bigcache = 0; icachesize = prom_getpropint(node, "icache-size", 0); if (icachesize > icache_size) icache_size = icachesize; linesize = l = prom_getpropint(node, "icache-line-size", 0); if (linesize > icache_line_size) icache_line_size = linesize; for (i = 0; (1 << i) < l && l; i++) /* void */; if ((1 << i) != l && l) panic("bad icache line size %d", l); totalsize = icachesize; if (totalsize == 0) totalsize = l * prom_getpropint(node, "icache-nlines", 64) * prom_getpropint(node, "icache-associativity", 1); cachesize = totalsize / prom_getpropint(node, "icache-associativity", 1); bigcache = cachesize; sep = ""; if (totalsize > 0) { aprint_normal("%s%ldK instruction (%ld b/l)", sep, (long)totalsize/1024, (long)linesize); sep = ", "; } dcachesize = prom_getpropint(node, "dcache-size", 0); if (dcachesize > dcache_size) dcache_size = dcachesize; linesize = l = prom_getpropint(node, "dcache-line-size", 0); if (linesize > dcache_line_size) dcache_line_size = linesize; for (i = 0; (1 << i) < l && l; i++) /* void */; if ((1 << i) != l && l) panic("bad dcache line size %d", l); totalsize = dcachesize; if (totalsize == 0) totalsize = l * prom_getpropint(node, "dcache-nlines", 128) * prom_getpropint(node, "dcache-associativity", 1); cachesize = totalsize / prom_getpropint(node, "dcache-associativity", 1); if (cachesize > bigcache) bigcache = cachesize; if (totalsize > 0) { aprint_normal("%s%ldK data (%ld b/l)", sep, (long)totalsize/1024, (long)linesize); sep = ", "; } linesize = l = prom_getpropint(node, "ecache-line-size", 0); for (i = 0; (1 << i) < l && l; i++) /* void */; if ((1 << i) != l && l) panic("bad ecache line size %d", l); totalsize = prom_getpropint(node, "ecache-size", 0); if (totalsize == 0) totalsize = l * prom_getpropint(node, "ecache-nlines", 32768) * prom_getpropint(node, "ecache-associativity", 1); cachesize = totalsize / prom_getpropint(node, "ecache-associativity", 1); if (cachesize > bigcache) bigcache = cachesize; if (totalsize > 0) { aprint_normal("%s%ldK external (%ld b/l)", sep, (long)totalsize/1024, (long)linesize); } aprint_normal("\n"); if (ecache_min_line_size == 0 || linesize < ecache_min_line_size) ecache_min_line_size = linesize; /* * Now that we know the size of the largest cache on this CPU, * re-color our pages. */ uvm_page_recolor(atop(bigcache)); /* XXX */ }
/* * Called back during autoconfiguration for each device found */ void device_register(device_t dev, void *aux) { device_t busdev = device_parent(dev); int ofnode = 0; /* * We don't know the type of 'aux' - it depends on the * bus this device attaches to. We are only interested in * certain bus types, this only is used to find the boot * device. */ if (busdev == NULL) { /* * Ignore mainbus0 itself, it certainly is not a boot * device. */ } else if (device_is_a(busdev, "mainbus")) { struct mainbus_attach_args *ma = aux; ofnode = ma->ma_node; } else if (device_is_a(busdev, "pci")) { struct pci_attach_args *pa = aux; ofnode = PCITAG_NODE(pa->pa_tag); } else if (device_is_a(busdev, "sbus") || device_is_a(busdev, "dma") || device_is_a(busdev, "ledma")) { struct sbus_attach_args *sa = aux; ofnode = sa->sa_node; } else if (device_is_a(busdev, "ebus")) { struct ebus_attach_args *ea = aux; ofnode = ea->ea_node; } else if (device_is_a(busdev, "iic")) { struct i2c_attach_args *ia = aux; if (ia->ia_name == NULL) /* indirect config */ return; ofnode = (int)ia->ia_cookie; } else if (device_is_a(dev, "sd") || device_is_a(dev, "cd")) { struct scsipibus_attach_args *sa = aux; struct scsipi_periph *periph = sa->sa_periph; int off = 0; /* * There are two "cd" attachments: * atapibus -> atabus -> controller * scsibus -> controller * We want the node of the controller. */ if (device_is_a(busdev, "atapibus")) { busdev = device_parent(busdev); /* * if the atapibus is connected to the secondary * channel of the atabus, we need an offset of 2 * to match OF's idea of the target number. * (i.e. on U5/U10 "cdrom" and "disk2" have the * same target encoding, though different names) */ if (periph->periph_channel->chan_channel == 1) off = 2; } ofnode = device_ofnode(device_parent(busdev)); dev_path_drive_match(dev, ofnode, periph->periph_target + off, 0, periph->periph_lun); return; } else if (device_is_a(dev, "wd")) { struct ata_device *adev = aux; ofnode = device_ofnode(device_parent(busdev)); dev_path_drive_match(dev, ofnode, adev->adev_channel*2+ adev->adev_drv_data->drive, 0, 0); return; } if (busdev == NULL) return; if (ofnode != 0) { uint8_t eaddr[ETHER_ADDR_LEN]; char tmpstr[32]; char tmpstr2[32]; int node; uint32_t id = 0; uint64_t nwwn = 0, pwwn = 0; prop_dictionary_t dict; prop_data_t blob; prop_number_t pwwnd = NULL, nwwnd = NULL; prop_number_t idd = NULL; device_setofnode(dev, ofnode); dev_path_exact_match(dev, ofnode); if (OF_getprop(ofnode, "name", tmpstr, sizeof(tmpstr)) <= 0) tmpstr[0] = 0; if (OF_getprop(ofnode, "device_type", tmpstr2, sizeof(tmpstr2)) <= 0) tmpstr2[0] = 0; /* * If this is a network interface, note the * mac address. */ if (strcmp(tmpstr, "network") == 0 || strcmp(tmpstr, "ethernet") == 0 || strcmp(tmpstr2, "network") == 0 || strcmp(tmpstr2, "ethernet") == 0 || OF_getprop(ofnode, "mac-address", &eaddr, sizeof(eaddr)) >= ETHER_ADDR_LEN || OF_getprop(ofnode, "local-mac-address", &eaddr, sizeof(eaddr)) >= ETHER_ADDR_LEN) { dict = device_properties(dev); /* * Is it a network interface with FCode? */ if (strcmp(tmpstr, "network") == 0 || strcmp(tmpstr2, "network") == 0) { prop_dictionary_set_bool(dict, "without-seeprom", true); prom_getether(ofnode, eaddr); } else { if (!prom_get_node_ether(ofnode, eaddr)) goto noether; } blob = prop_data_create_data(eaddr, ETHER_ADDR_LEN); prop_dictionary_set(dict, "mac-address", blob); prop_object_release(blob); of_to_dataprop(dict, ofnode, "shared-pins", "shared-pins"); } noether: /* is this a FC node? */ if (strcmp(tmpstr, "scsi-fcp") == 0) { dict = device_properties(dev); if (OF_getprop(ofnode, "port-wwn", &pwwn, sizeof(pwwn)) == sizeof(pwwn)) { pwwnd = prop_number_create_unsigned_integer(pwwn); prop_dictionary_set(dict, "port-wwn", pwwnd); prop_object_release(pwwnd); } if (OF_getprop(ofnode, "node-wwn", &nwwn, sizeof(nwwn)) == sizeof(nwwn)) { nwwnd = prop_number_create_unsigned_integer(nwwn); prop_dictionary_set(dict, "node-wwn", nwwnd); prop_object_release(nwwnd); } } /* is this an spi device? look for scsi-initiator-id */ if (strcmp(tmpstr2, "scsi") == 0 || strcmp(tmpstr2, "scsi-2") == 0) { dict = device_properties(dev); for (node = ofnode; node != 0; node = OF_parent(node)) { if (OF_getprop(node, "scsi-initiator-id", &id, sizeof(id)) <= 0) continue; idd = prop_number_create_unsigned_integer(id); prop_dictionary_set(dict, "scsi-initiator-id", idd); prop_object_release(idd); break; } } } /* * Check for I2C busses and add data for their direct configuration. */ if (device_is_a(dev, "iic")) { int busnode = device_ofnode(busdev); if (busnode) { prop_dictionary_t props = device_properties(busdev); prop_object_t cfg = prop_dictionary_get(props, "i2c-child-devices"); if (!cfg) { int node; const char *name; /* * pmu's i2c devices are under the "i2c" node, * so find it out. */ name = prom_getpropstring(busnode, "name"); if (strcmp(name, "pmu") == 0) { for (node = OF_child(busnode); node != 0; node = OF_peer(node)) { name = prom_getpropstring(node, "name"); if (strcmp(name, "i2c") == 0) { busnode = node; break; } } } of_enter_i2c_devs(props, busnode, sizeof(cell_t)); } } /* * Add SPARCle spdmem devices (0x50 and 0x51) that the * firmware does not know about. */ if (!strcmp(machine_model, "TAD,SPARCLE")) { prop_dictionary_t props = device_properties(busdev); prop_array_t cfg = prop_array_create(); int i; DPRINTF(ACDB_PROBE, ("\nAdding spdmem for SPARCle ")); for (i = 0x50; i <= 0x51; i++) { prop_dictionary_t spd = prop_dictionary_create(); prop_dictionary_set_cstring(spd, "name", "dimm-spd"); prop_dictionary_set_uint32(spd, "addr", i); prop_dictionary_set_uint64(spd, "cookie", 0); prop_array_add(cfg, spd); prop_object_release(spd); } prop_dictionary_set(props, "i2c-child-devices", cfg); prop_object_release(cfg); } } /* set properties for PCI framebuffers */ if (device_is_a(busdev, "pci")) { /* see if this is going to be console */ struct pci_attach_args *pa = aux; prop_dictionary_t dict; int sub; int console = 0; dict = device_properties(dev); /* we only care about display devices from here on */ if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY) return; console = (ofnode == console_node); if (!console) { /* * see if any child matches since OF attaches * nodes for each head and /chosen/stdout * points to the head rather than the device * itself in this case */ sub = OF_child(ofnode); while ((sub != 0) && (sub != console_node)) { sub = OF_peer(sub); } if (sub == console_node) { console = true; } } copyprops(busdev, ofnode, dict, console); if (console) { uint64_t cmap_cb; prop_dictionary_set_uint32(dict, "instance_handle", console_instance); gfb_cb.gcc_cookie = (void *)(intptr_t)console_instance; gfb_cb.gcc_set_mapreg = of_set_palette; cmap_cb = (uint64_t)(uintptr_t)&gfb_cb; prop_dictionary_set_uint64(dict, "cmap_callback", cmap_cb); } #ifdef notyet else { int width; /* * the idea is to 'open' display devices with no useful * properties, in the hope that the firmware will * properly initialize them and we can run things like * genfb on them */ if (OF_getprop(node, "width", &width, sizeof(width)) != 4) { instance = OF_open(name); #endif } } /* * Called back after autoconfiguration of a device is done */ void device_register_post_config(device_t dev, void *aux) { if (booted_device == NULL && device_is_a(dev, "sd")) { struct scsipibus_attach_args *sa = aux; struct scsipi_periph *periph = sa->sa_periph; uint64_t wwn = 0; int ofnode; /* * If this is a FC-AL drive it will have * aquired its WWN device property by now, * so we can properly match it. */ if (prop_dictionary_get_uint64(device_properties(dev), "port-wwn", &wwn)) { /* * Different to what we do in device_register, * we do not pass the "controller" ofnode, * because FC-AL devices attach below a "fp" node, * E.g.: /pci/SUNW,qlc@4/fp@0,0/disk * and we need the parent of "disk" here. */ ofnode = device_ofnode( device_parent(device_parent(dev))); for (ofnode = OF_child(ofnode); ofnode != 0 && booted_device == NULL; ofnode = OF_peer(ofnode)) { dev_path_drive_match(dev, ofnode, periph->periph_target, wwn, periph->periph_lun); } } } } static void copyprops(device_t busdev, int node, prop_dictionary_t dict, int is_console) { device_t cntrlr; prop_dictionary_t psycho; paddr_t fbpa, mem_base = 0; uint32_t temp, fboffset; uint32_t fbaddr = 0; int options; char output_device[256]; char *pos; cntrlr = device_parent(busdev); if (cntrlr != NULL) { psycho = device_properties(cntrlr); prop_dictionary_get_uint64(psycho, "mem_base", &mem_base); } if (is_console) prop_dictionary_set_bool(dict, "is_console", 1); of_to_uint32_prop(dict, node, "width", "width"); of_to_uint32_prop(dict, node, "height", "height"); of_to_uint32_prop(dict, node, "linebytes", "linebytes"); if (!of_to_uint32_prop(dict, node, "depth", "depth") && /* Some cards have an extra space in the property name */ !of_to_uint32_prop(dict, node, "depth ", "depth")) { /* * XXX we should check linebytes vs. width but those * FBs that don't have a depth property ( /chaos/control... ) * won't have linebytes either */ prop_dictionary_set_uint32(dict, "depth", 8); } OF_getprop(node, "address", &fbaddr, sizeof(fbaddr)); if (fbaddr != 0) { pmap_extract(pmap_kernel(), fbaddr, &fbpa); #ifdef DEBUG printf("membase: %lx fbpa: %lx\n", (unsigned long)mem_base, (unsigned long)fbpa); #endif if (mem_base == 0) { /* XXX this is guesswork */ fboffset = (uint32_t)(fbpa & 0xffffffff); } fboffset = (uint32_t)(fbpa - mem_base); prop_dictionary_set_uint32(dict, "address", fboffset); } if (!of_to_dataprop(dict, node, "EDID", "EDID")) of_to_dataprop(dict, node, "edid", "EDID"); temp = 0; if (OF_getprop(node, "ATY,RefCLK", &temp, sizeof(temp)) != 4) { OF_getprop(OF_parent(node), "ATY,RefCLK", &temp, sizeof(temp)); } if (temp != 0) prop_dictionary_set_uint32(dict, "refclk", temp / 10); /* * finally, let's see if there's a video mode specified in * output-device and pass it on so drivers like radeonfb * can do their thing */ if (!is_console) return; options = OF_finddevice("/options"); if ((options == 0) || (options == -1)) return; if (OF_getprop(options, "output-device", output_device, 256) == 0) return; /* find the mode string if there is one */ pos = strstr(output_device, ":r"); if (pos == NULL) return; prop_dictionary_set_cstring(dict, "videomode", pos + 2); } static void of_set_palette(void *cookie, int index, int r, int g, int b) { int ih = (int)((intptr_t)cookie); OF_call_method_1("color!", ih, 4, r, g, b, index); }
/* * Match a device_t against the bootpath, by * comparing its firmware package handle and calculating * the target/lun suffix and comparing that against * the bootpath remainder. */ static void dev_path_drive_match(device_t dev, int ctrlnode, int target, uint64_t wwn, int lun) { int child = 0, ide_node = 0; char buf[OFPATHLEN]; DPRINTF(ACDB_BOOTDEV, ("dev_path_drive_match: %s, controller %x, " "target %d wwn %016" PRIx64 " lun %d\n", device_xname(dev), ctrlnode, target, wwn, lun)); /* * The ofbootpackage points to a disk on this controller, so * iterate over all child nodes and compare. */ for (child = prom_firstchild(ctrlnode); child != 0; child = prom_nextsibling(child)) if (child == ofbootpackage) break; if (child != ofbootpackage) { /* * Try Mac firmware style (also used by QEMU/OpenBIOS): * below the controller there is an intermediate node * for each IDE channel, and individual targets always * are "@0" */ for (ide_node = prom_firstchild(ctrlnode); ide_node != 0; ide_node = prom_nextsibling(ide_node)) { const char * name = prom_getpropstring(ide_node, "device_type"); if (strcmp(name, "ide") != 0) continue; for (child = prom_firstchild(ide_node); child != 0; child = prom_nextsibling(child)) if (child == ofbootpackage) break; if (child == ofbootpackage) break; } } if (child == ofbootpackage) { const char * name = prom_getpropstring(child, "name"); /* boot device is on this controller */ DPRINTF(ACDB_BOOTDEV, ("found controller of bootdevice\n")); /* * Note: "child" here is == ofbootpackage (s.a.), which * may be completely wrong for the device we are checking, * what we realy do here is to match "target" and "lun". */ if (wwn) snprintf(buf, sizeof(buf), "%s@w%016" PRIx64 ",%d", name, wwn, lun); else if (ide_node) snprintf(buf, sizeof(buf), "%s@0", device_is_a(dev, "cd") ? "cdrom" : "disk"); else snprintf(buf, sizeof(buf), "%s@%d,%d", name, target, lun); if (ofboottarget && strcmp(buf, ofboottarget) == 0) { booted_device = dev; if (ofbootpartition) booted_partition = *ofbootpartition - 'a'; DPRINTF(ACDB_BOOTDEV, ("found boot device: %s" ", partition %d\n", device_xname(dev), booted_partition)); } } }
/* * SUNW,psycho initialisation .. * - find the per-psycho registers * - figure out the IGN. * - find our partner psycho * - configure ourselves * - bus range, bus, * - get interrupt-map and interrupt-map-mask * - setup the chipsets. * - if we're the first of the pair, initialise the IOMMU, otherwise * just copy its tags and addresses. */ static void psycho_attach(device_t parent, device_t self, void *aux) { struct psycho_softc *sc = device_private(self); struct psycho_softc *osc = NULL; struct psycho_pbm *pp; struct pcibus_attach_args pba; struct mainbus_attach_args *ma = aux; struct psycho_ranges *pr; prop_dictionary_t dict; bus_space_handle_t bh; uint64_t csr, mem_base; int psycho_br[2], n, i; bus_space_handle_t pci_ctl; char *model = prom_getpropstring(ma->ma_node, "model"); aprint_normal("\n"); sc->sc_dev = self; sc->sc_node = ma->ma_node; sc->sc_bustag = ma->ma_bustag; sc->sc_dmatag = ma->ma_dmatag; sc->sc_last_stick = 0; if (psycho0 == NULL) psycho0 = sc; DPRINTF(PDB_STICK, ("init psycho0 %lx\n", (long)sc)); /* * Identify the device. */ for (i=0; psycho_names[i].p_name; i++) if (strcmp(model, psycho_names[i].p_name) == 0) { sc->sc_mode = psycho_names[i].p_type; goto found; } model = prom_getpropstring(ma->ma_node, "compatible"); for (i=0; psycho_names[i].p_name; i++) if (strcmp(model, psycho_names[i].p_name) == 0) { sc->sc_mode = psycho_names[i].p_type; goto found; } panic("unknown psycho model %s", model); found: /* * The psycho gets three register banks: * (0) per-PBM configuration and status registers * (1) per-PBM PCI configuration space, containing only the * PBM 256-byte PCI header * (2) the shared psycho configuration registers (struct psychoreg) */ /* Register layouts are different. stuupid. */ if (sc->sc_mode == PSYCHO_MODE_PSYCHO) { sc->sc_basepaddr = (paddr_t)ma->ma_reg[2].ur_paddr; if (ma->ma_naddress > 2) { sparc_promaddr_to_handle(sc->sc_bustag, ma->ma_address[2], &sc->sc_bh); sparc_promaddr_to_handle(sc->sc_bustag, ma->ma_address[0], &pci_ctl); sc->sc_regs = (struct psychoreg *) bus_space_vaddr(sc->sc_bustag, sc->sc_bh); } else if (ma->ma_nreg > 2) { /* We need to map this in ourselves. */ if (bus_space_map(sc->sc_bustag, ma->ma_reg[2].ur_paddr, ma->ma_reg[2].ur_len, BUS_SPACE_MAP_LINEAR, &sc->sc_bh)) panic("psycho_attach: cannot map regs"); sc->sc_regs = (struct psychoreg *) bus_space_vaddr(sc->sc_bustag, sc->sc_bh); if (bus_space_map(sc->sc_bustag, ma->ma_reg[0].ur_paddr, ma->ma_reg[0].ur_len, BUS_SPACE_MAP_LINEAR, &pci_ctl)) panic("psycho_attach: cannot map ctl"); } else panic("psycho_attach: %d not enough registers", ma->ma_nreg); } else { sc->sc_basepaddr = (paddr_t)ma->ma_reg[0].ur_paddr; if (ma->ma_naddress) { sparc_promaddr_to_handle(sc->sc_bustag, ma->ma_address[0], &sc->sc_bh); sc->sc_regs = (struct psychoreg *) bus_space_vaddr(sc->sc_bustag, sc->sc_bh); bus_space_subregion(sc->sc_bustag, sc->sc_bh, offsetof(struct psychoreg, psy_pcictl), sizeof(struct pci_ctl), &pci_ctl); } else if (ma->ma_nreg) {
void magma_attach(device_t parent, device_t self, void *aux) { struct sbus_attach_args *sa = aux; struct magma_softc *sc = device_private(self); struct magma_board_info *card; bus_space_handle_t bh; char *magma_prom, *clockstr; int cd_clock; int node, chip; sc->ms_dev = self; node = sa->sa_node; /* * Find the card model. * Older models all have sbus node name `MAGMA_Sp' (see * `supported_cards[]' above), and must be distinguished * by the `magma_prom' property. */ magma_prom = prom_getpropstring(node, "magma_prom"); for (card = supported_cards; card->mb_name != NULL; card++) { if (strcmp(sa->sa_name, card->mb_sbusname) != 0) /* Sbus node name doesn't match */ continue; if (strcmp(magma_prom, card->mb_name) == 0) /* Model name match */ break; } if( card->mb_name == NULL ) { printf(": %s (unsupported)\n", magma_prom); return; } dprintf((" addr %p", sc)); printf(": %s\n", card->mb_realname); sc->ms_board = card; sc->ms_ncd1400 = card->mb_ncd1400; sc->ms_ncd1190 = card->mb_ncd1190; if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset, sa->sa_size, BUS_SPACE_MAP_LINEAR, &bh) != 0) { aprint_error("%s @ sbus: cannot map registers\n", device_xname(self)); return; } /* the SVCACK* lines are daisychained */ sc->ms_svcackr = (char *)bus_space_vaddr(sa->sa_bustag, bh) + card->mb_svcackr; sc->ms_svcackt = (char *)bus_space_vaddr(sa->sa_bustag, bh) + card->mb_svcackt; sc->ms_svcackm = (char *)bus_space_vaddr(sa->sa_bustag, bh) + card->mb_svcackm; /* * Find the clock speed; it's the same for all CD1400 chips * on the board. */ clockstr = prom_getpropstring(node, "clock"); if (*clockstr == '\0') /* Default to 25MHz */ cd_clock = 25; else { cd_clock = 0; while (*clockstr != '\0') cd_clock = (cd_clock * 10) + (*clockstr++ - '0'); } /* init the cd1400 chips */ for( chip = 0 ; chip < card->mb_ncd1400 ; chip++ ) { struct cd1400 *cd = &sc->ms_cd1400[chip]; cd->cd_clock = cd_clock; cd->cd_reg = (char *)bus_space_vaddr(sa->sa_bustag, bh) + card->mb_cd1400[chip]; /* prom_getpropstring(node, "chiprev"); */ /* seemingly the Magma drivers just ignore the propstring */ cd->cd_chiprev = cd1400_read_reg(cd, CD1400_GFRCR); dprintf(("%s attach CD1400 %d addr %p rev %x clock %dMHz\n", device_xname(sc->ms_dev), chip, cd->cd_reg, cd->cd_chiprev, cd->cd_clock)); /* clear GFRCR */ cd1400_write_reg(cd, CD1400_GFRCR, 0x00); /* reset whole chip */ cd1400_write_ccr(cd, CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET); /* wait for revision code to be restored */ while( cd1400_read_reg(cd, CD1400_GFRCR) != cd->cd_chiprev ) ; /* set the Prescaler Period Register to tick at 1ms */ cd1400_write_reg(cd, CD1400_PPR, ((cd->cd_clock * 1000000 / CD1400_PPR_PRESCALER + 500) / 1000)); /* The LC2+1Sp card is the only card that doesn't have * a CD1190 for the parallel port, but uses channel 0 of * the CD1400, so we make a note of it for later and set up * the CD1400 for parallel mode operation. */ if( card->mb_npar && card->mb_ncd1190 == 0 ) { cd1400_write_reg(cd, CD1400_GCR, CD1400_GCR_PARALLEL); cd->cd_parmode = 1; } } /* init the cd1190 chips */ for( chip = 0 ; chip < card->mb_ncd1190 ; chip++ ) { struct cd1190 *cd = &sc->ms_cd1190[chip]; cd->cd_reg = (char *)bus_space_vaddr(sa->sa_bustag, bh) + card->mb_cd1190[chip]; /* XXX don't know anything about these chips yet */ printf("%s: CD1190 %d addr %p (unsupported)\n", device_xname(self), chip, cd->cd_reg); } /* configure the children */ (void)config_found(self, mtty_match, NULL); (void)config_found(self, mbpp_match, NULL); /* * Establish the interrupt handlers. */ if (sa->sa_nintr == 0) return; /* No interrupts to service!? */ (void)bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_SERIAL, magma_hard, sc); sc->ms_sicookie = softint_establish(SOFTINT_SERIAL, magma_soft, sc); if (sc->ms_sicookie == NULL) { aprint_normal("\n"); aprint_error_dev(sc->ms_dev, "cannot establish soft int handler\n"); return; } evcnt_attach_dynamic(&sc->ms_intrcnt, EVCNT_TYPE_INTR, NULL, device_xname(sc->ms_dev), "intr"); }
void dmaattach_sbus(device_t parent, device_t self, void *aux) { struct dma_softc *dsc = device_private(self); struct lsi64854_softc *sc = &dsc->sc_lsi64854; struct sbus_attach_args *sa = aux; struct sbus_softc *sbsc = device_private(parent); bus_space_tag_t sbt; int sbusburst, burst; int node; node = sa->sa_node; sc->sc_dev = self; sc->sc_bustag = sa->sa_bustag; sc->sc_dmatag = sa->sa_dmatag; /* Map registers */ if (sa->sa_npromvaddrs) { sbus_promaddr_to_handle(sa->sa_bustag, sa->sa_promvaddrs[0], &sc->sc_regs); } else { if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset, sa->sa_size, 0, &sc->sc_regs) != 0) { aprint_error(": cannot map registers\n"); return; } } /* * Get transfer burst size from PROM and plug it into the * controller registers. This is needed on the Sun4m; do * others need it too? */ sbusburst = sbsc->sc_burst; if (sbusburst == 0) sbusburst = SBUS_BURST_32 - 1; /* 1->16 */ burst = prom_getpropint(node,"burst-sizes", -1); if (burst == -1) /* take SBus burst sizes */ burst = sbusburst; /* Clamp at parent's burst sizes */ burst &= sbusburst; sc->sc_burst = (burst & SBUS_BURST_32) ? 32 : (burst & SBUS_BURST_16) ? 16 : 0; if (device_is_a(self, "ledma")) { char *cabletype; uint32_t csr; /* * Check to see which cable type is currently active and * set the appropriate bit in the ledma csr so that it * gets used. If we didn't netboot, the PROM won't have * the "cable-selection" property; default to TP and then * the user can change it via a "media" option to ifconfig. */ cabletype = prom_getpropstring(node, "cable-selection"); csr = L64854_GCSR(sc); if (strcmp(cabletype, "tpe") == 0) { csr |= E_TP_AUI; } else if (strcmp(cabletype, "aui") == 0) { csr &= ~E_TP_AUI; } else { /* assume TP if nothing there */ csr |= E_TP_AUI; } L64854_SCSR(sc, csr); delay(20000); /* manual says we need a 20ms delay */ sc->sc_channel = L64854_CHANNEL_ENET; } else { sc->sc_channel = L64854_CHANNEL_SCSI; } sbus_establish(&dsc->sc_sd, self); if ((sbt = bus_space_tag_alloc(sc->sc_bustag, dsc)) == NULL) { aprint_error(": out of memory\n"); return; } sbt->sparc_intr_establish = dmabus_intr_establish; lsi64854_attach(sc); /* Attach children */ for (node = firstchild(sa->sa_node); node; node = nextsibling(node)) { struct sbus_attach_args sax; sbus_setup_attach_args(sbsc, sbt, sc->sc_dmatag, node, &sax); (void)config_found(self, (void *)&sax, dmaprint_sbus); sbus_destroy_attach_args(&sax); } }
void fhc_attach(struct fhc_softc *sc) { int node0, node; u_int32_t ctrl; printf(" board %d: %s\n", sc->sc_board, prom_getpropstring(sc->sc_node, "board-model")); sc->sc_cbt = fhc_alloc_bus_tag(sc); sc->sc_ign = sc->sc_board << 1; bus_space_write_4(sc->sc_bt, sc->sc_ireg, FHC_I_IGN, sc->sc_ign); sc->sc_ign = bus_space_read_4(sc->sc_bt, sc->sc_ireg, FHC_I_IGN); ctrl = bus_space_read_4(sc->sc_bt, sc->sc_preg, FHC_P_CTRL); if (!sc->sc_is_central) ctrl |= FHC_P_CTRL_IXIST; ctrl &= ~(FHC_P_CTRL_AOFF | FHC_P_CTRL_BOFF | FHC_P_CTRL_SLINE); bus_space_write_4(sc->sc_bt, sc->sc_preg, FHC_P_CTRL, ctrl); bus_space_read_4(sc->sc_bt, sc->sc_preg, FHC_P_CTRL); /* clear interrupts */ bus_space_write_4(sc->sc_bt, sc->sc_freg, FHC_F_ICLR, 0); bus_space_read_4(sc->sc_bt, sc->sc_freg, FHC_F_ICLR); bus_space_write_4(sc->sc_bt, sc->sc_sreg, FHC_S_ICLR, 0); bus_space_read_4(sc->sc_bt, sc->sc_sreg, FHC_S_ICLR); bus_space_write_4(sc->sc_bt, sc->sc_ureg, FHC_U_ICLR, 0); bus_space_read_4(sc->sc_bt, sc->sc_ureg, FHC_U_ICLR); bus_space_write_4(sc->sc_bt, sc->sc_treg, FHC_T_ICLR, 0); bus_space_read_4(sc->sc_bt, sc->sc_treg, FHC_T_ICLR); prom_getprop(sc->sc_node, "ranges", sizeof(struct fhc_range), &sc->sc_nrange, (void **)&sc->sc_range); node0 = firstchild(sc->sc_node); for (node = node0; node; node = nextsibling(node)) { struct fhc_attach_args fa; #if 0 if (!checkstatus(node)) continue; #endif bzero(&fa, sizeof(fa)); fa.fa_node = node; fa.fa_bustag = sc->sc_cbt; if (fhc_get_string(fa.fa_node, "name", &fa.fa_name)) { printf("can't fetch name for node 0x%x\n", node); continue; } prom_getprop(node, "reg", sizeof(struct fhc_reg), &fa.fa_nreg, (void **)&fa.fa_reg); prom_getprop(node, "interrupts", sizeof(int), &fa.fa_nintr, (void **)&fa.fa_intr); prom_getprop(node, "address", sizeof(*fa.fa_promvaddrs), &fa.fa_npromvaddrs, (void **)&fa.fa_promvaddrs); (void)config_found(sc->sc_dev, (void *)&fa, fhc_print); if (fa.fa_name != NULL) free(fa.fa_name, M_DEVBUF); if (fa.fa_reg != NULL) free(fa.fa_reg, M_DEVBUF); if (fa.fa_intr != NULL) free(fa.fa_intr, M_DEVBUF); if (fa.fa_promvaddrs != NULL) free(fa.fa_promvaddrs, M_DEVBUF); } }