static void ld_aac_attach(device_t parent, device_t self, void *aux) { struct aac_attach_args *aaca = aux; struct ld_aac_softc *sc = device_private(self); struct ld_softc *ld = &sc->sc_ld; struct aac_softc *aac = device_private(parent); struct aac_drive *hdr = &aac->sc_hdr[aaca->aaca_unit]; ld->sc_dv = self; sc->sc_hwunit = aaca->aaca_unit; ld->sc_flags = LDF_ENABLED; ld->sc_maxxfer = AAC_MAX_XFER(aac); ld->sc_secperunit = hdr->hd_size; ld->sc_secsize = AAC_SECTOR_SIZE; ld->sc_maxqueuecnt = (aac->sc_max_fibs - AAC_NCCBS_RESERVE) / aac->sc_nunits; ld->sc_start = ld_aac_start; ld->sc_dump = ld_aac_dump; aprint_normal(": %s\n", aac_describe_code(aac_container_types, hdr->hd_devtype)); ldattach(ld); }
void ld_cac_attach(struct device *parent, struct device *self, void *aux) { struct cac_drive_info dinfo; struct cac_attach_args *caca; struct ld_softc *ld; struct ld_cac_softc *sc; struct cac_softc *cac; const char *type; sc = (struct ld_cac_softc *)self; ld = &sc->sc_ld; caca = (struct cac_attach_args *)aux; sc->sc_hwunit = caca->caca_unit; cac = (struct cac_softc *)parent; if (cac_cmd(cac, CAC_CMD_GET_LOG_DRV_INFO, &dinfo, sizeof(dinfo), sc->sc_hwunit, 0, CAC_CCB_DATA_IN, NULL)) { printf("%s: CMD_GET_LOG_DRV_INFO failed\n", self->dv_xname); return; } ld->sc_secsize = CAC_GET2(dinfo.secsize); ld->sc_maxxfer = CAC_MAX_XFER; ld->sc_maxqueuecnt = CAC_MAX_CCBS / cac->sc_nunits; /* XXX */ ld->sc_secperunit = CAC_GET2(dinfo.ncylinders) * CAC_GET1(dinfo.nheads) * CAC_GET1(dinfo.nsectors); ld->sc_start = ld_cac_start; ld->sc_dump = ld_cac_dump; switch (CAC_GET1(dinfo.mirror)) { case 0: type = "standalone disk or RAID0"; break; case 1: type = "RAID4"; break; case 2: type = "RAID1"; break; case 3: type = "RAID5"; break; default: type = "unknown type of"; break; } printf(": %s array\n", type); /* XXX We should verify this... */ ld->sc_flags = LDF_ENABLED; ldattach(ld); }
void ld_cac_attach(device_t parent, device_t self, void *aux) { struct cac_drive_info dinfo; struct cac_attach_args *caca; struct ld_cac_softc *sc = device_private(self); struct cac_softc *cac = device_private(parent); struct ld_softc *ld = &sc->sc_ld; const char *type; caca = aux; ld->sc_dv = self; sc->sc_mutex = &cac->sc_mutex; sc->sc_hwunit = caca->caca_unit; if (cac_cmd(cac, CAC_CMD_GET_LOG_DRV_INFO, &dinfo, sizeof(dinfo), sc->sc_hwunit, 0, CAC_CCB_DATA_IN, NULL)) { aprint_error(": CMD_GET_LOG_DRV_INFO failed\n"); return; } ld->sc_secsize = CAC_GET2(dinfo.secsize); ld->sc_maxxfer = CAC_MAX_XFER; ld->sc_maxqueuecnt = (CAC_MAX_CCBS - 1) / cac->sc_nunits; ld->sc_secperunit = CAC_GET2(dinfo.ncylinders) * CAC_GET1(dinfo.nheads) * CAC_GET1(dinfo.nsectors); ld->sc_start = ld_cac_start; ld->sc_dump = ld_cac_dump; switch (CAC_GET1(dinfo.mirror)) { case 0: type = "standalone disk or RAID0"; break; case 1: type = "RAID4"; break; case 2: type = "RAID1"; break; case 3: type = "RAID5"; break; default: type = "unknown type of"; break; } aprint_normal(": %s array\n", type); /* XXX We should verify this... */ ld->sc_flags = LDF_ENABLED; ldattach(ld); }
static void ld_sdmmc_doattach(void *arg) { struct ld_sdmmc_softc *sc = (struct ld_sdmmc_softc *)arg; struct ld_softc *ld = &sc->sc_ld; struct sdmmc_softc *ssc = device_private(device_parent(ld->sc_dv)); ldattach(ld); aprint_normal_dev(ld->sc_dv, "%d-bit width, bus clock", sc->sc_sf->width); if ((ssc->sc_busclk / 1000) != 0) aprint_normal(" %u.%03u MHz\n", ssc->sc_busclk / 1000, ssc->sc_busclk % 1000); else aprint_normal(" %u KHz\n", ssc->sc_busclk % 1000); config_pending_decr(ld->sc_dv); kthread_exit(0); }
static void ld_twa_attach(device_t parent, device_t self, void *aux) { struct twa_attach_args *twa_args = aux; struct ld_twa_softc *sc = device_private(self); struct ld_softc *ld = &sc->sc_ld; struct twa_softc *twa = device_private(parent); ld->sc_dv = self; twa_register_callbacks(twa, twa_args->twaa_unit, &ld_twa_callbacks); sc->sc_hwunit = twa_args->twaa_unit; ld->sc_maxxfer = twa_get_maxxfer(twa_get_maxsegs()); ld->sc_secperunit = twa->sc_units[sc->sc_hwunit].td_size; ld->sc_flags = LDF_ENABLED; ld->sc_secsize = TWA_SECTOR_SIZE; ld->sc_maxqueuecnt = twa->sc_units[sc->sc_hwunit].td_openings; ld->sc_start = ld_twa_start; ld->sc_dump = ld_twa_dump; ld->sc_flush = ld_twa_flush; ldattach(ld); }
static void ld_virtio_attach(device_t parent, device_t self, void *aux) { struct ld_virtio_softc *sc = device_private(self); struct ld_softc *ld = &sc->sc_ld; struct virtio_softc *vsc = device_private(parent); uint32_t features; char buf[256]; int qsize, maxxfersize, maxnsegs; if (vsc->sc_child != NULL) { aprint_normal(": child already attached for %s; " "something wrong...\n", device_xname(parent)); return; } sc->sc_dev = self; sc->sc_virtio = vsc; vsc->sc_child = self; vsc->sc_ipl = IPL_BIO; vsc->sc_vqs = &sc->sc_vq; vsc->sc_nvqs = 1; vsc->sc_config_change = NULL; vsc->sc_intrhand = virtio_vq_intr; vsc->sc_flags = 0; features = virtio_negotiate_features(vsc, (VIRTIO_BLK_F_SIZE_MAX | VIRTIO_BLK_F_SEG_MAX | VIRTIO_BLK_F_GEOMETRY | VIRTIO_BLK_F_RO | VIRTIO_BLK_F_BLK_SIZE)); if (features & VIRTIO_BLK_F_RO) sc->sc_readonly = 1; else sc->sc_readonly = 0; snprintb(buf, sizeof(buf), VIRTIO_BLK_FLAG_BITS, features); aprint_normal(": Features: %s\n", buf); aprint_naive("\n"); if (features & VIRTIO_BLK_F_BLK_SIZE) { ld->sc_secsize = virtio_read_device_config_4(vsc, VIRTIO_BLK_CONFIG_BLK_SIZE); } else ld->sc_secsize = 512; /* At least genfs_io assumes maxxfer == MAXPHYS. */ if (features & VIRTIO_BLK_F_SIZE_MAX) { maxxfersize = virtio_read_device_config_4(vsc, VIRTIO_BLK_CONFIG_SIZE_MAX); if (maxxfersize < MAXPHYS) { aprint_error_dev(sc->sc_dev, "Too small SIZE_MAX %dK minimum is %dK\n", maxxfersize / 1024, MAXPHYS / 1024); // goto err; maxxfersize = MAXPHYS; } else if (maxxfersize > MAXPHYS) { aprint_normal_dev(sc->sc_dev, "Clip SEG_MAX from %dK to %dK\n", maxxfersize / 1024, MAXPHYS / 1024); maxxfersize = MAXPHYS; } } else maxxfersize = MAXPHYS; if (features & VIRTIO_BLK_F_SEG_MAX) { maxnsegs = virtio_read_device_config_4(vsc, VIRTIO_BLK_CONFIG_SEG_MAX); if (maxnsegs < VIRTIO_BLK_MIN_SEGMENTS) { aprint_error_dev(sc->sc_dev, "Too small SEG_MAX %d minimum is %d\n", maxnsegs, VIRTIO_BLK_MIN_SEGMENTS); maxnsegs = maxxfersize / NBPG; // goto err; } } else maxnsegs = maxxfersize / NBPG; /* 2 for the minimum size */ maxnsegs += VIRTIO_BLK_MIN_SEGMENTS; if (virtio_alloc_vq(vsc, &sc->sc_vq, 0, maxxfersize, maxnsegs, "I/O request") != 0) { goto err; } qsize = sc->sc_vq.vq_num; sc->sc_vq.vq_done = ld_virtio_vq_done; ld->sc_dv = self; ld->sc_secperunit = virtio_read_device_config_8(vsc, VIRTIO_BLK_CONFIG_CAPACITY); ld->sc_maxxfer = maxxfersize; if (features & VIRTIO_BLK_F_GEOMETRY) { ld->sc_ncylinders = virtio_read_device_config_2(vsc, VIRTIO_BLK_CONFIG_GEOMETRY_C); ld->sc_nheads = virtio_read_device_config_1(vsc, VIRTIO_BLK_CONFIG_GEOMETRY_H); ld->sc_nsectors = virtio_read_device_config_1(vsc, VIRTIO_BLK_CONFIG_GEOMETRY_S); } ld->sc_maxqueuecnt = qsize; if (ld_virtio_alloc_reqs(sc, qsize) < 0) goto err; ld->sc_dump = ld_virtio_dump; ld->sc_flush = NULL; ld->sc_start = ld_virtio_start; ld->sc_flags = LDF_ENABLED; ldattach(ld, BUFQ_DISK_DEFAULT_STRAT); return; err: vsc->sc_child = (void*)1; return; }
static void ld_virtio_attach(device_t parent, device_t self, void *aux) { struct ld_virtio_softc *sc = device_private(self); struct ld_softc *ld = &sc->sc_ld; struct virtio_softc *vsc = device_private(parent); uint32_t features; int qsize, maxxfersize; if (vsc->sc_child != NULL) { aprint_normal(": child already attached for %s; " "something wrong...\n", device_xname(parent)); return; } aprint_normal("\n"); aprint_naive("\n"); sc->sc_dev = self; sc->sc_virtio = vsc; vsc->sc_child = self; vsc->sc_ipl = IPL_BIO; vsc->sc_vqs = &sc->sc_vq[0]; vsc->sc_nvqs = 1; vsc->sc_config_change = 0; vsc->sc_intrhand = virtio_vq_intr; vsc->sc_flags = 0; features = virtio_negotiate_features(vsc, (VIRTIO_BLK_F_SIZE_MAX | VIRTIO_BLK_F_SEG_MAX | VIRTIO_BLK_F_GEOMETRY | VIRTIO_BLK_F_RO | VIRTIO_BLK_F_BLK_SIZE)); if (features & VIRTIO_BLK_F_RO) sc->sc_readonly = 1; else sc->sc_readonly = 0; ld->sc_secsize = 512; if (features & VIRTIO_BLK_F_BLK_SIZE) { ld->sc_secsize = virtio_read_device_config_4(vsc, VIRTIO_BLK_CONFIG_BLK_SIZE); } maxxfersize = MAXPHYS; #if 0 /* At least genfs_io assumes maxxfer == MAXPHYS. */ if (features & VIRTIO_BLK_F_SEG_MAX) { maxxfersize = virtio_read_device_config_4(vsc, VIRTIO_BLK_CONFIG_SEG_MAX) * ld->sc_secsize; if (maxxfersize > MAXPHYS) maxxfersize = MAXPHYS; } #endif if (virtio_alloc_vq(vsc, &sc->sc_vq[0], 0, maxxfersize, maxxfersize / NBPG + 2, "I/O request") != 0) { goto err; } qsize = sc->sc_vq[0].vq_num; sc->sc_vq[0].vq_done = ld_virtio_vq_done; ld->sc_dv = self; ld->sc_secperunit = virtio_read_device_config_8(vsc, VIRTIO_BLK_CONFIG_CAPACITY); ld->sc_maxxfer = maxxfersize; if (features & VIRTIO_BLK_F_GEOMETRY) { ld->sc_ncylinders = virtio_read_device_config_2(vsc, VIRTIO_BLK_CONFIG_GEOMETRY_C); ld->sc_nheads = virtio_read_device_config_1(vsc, VIRTIO_BLK_CONFIG_GEOMETRY_H); ld->sc_nsectors = virtio_read_device_config_1(vsc, VIRTIO_BLK_CONFIG_GEOMETRY_S); } ld->sc_maxqueuecnt = qsize; if (ld_virtio_alloc_reqs(sc, qsize) < 0) goto err; mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_BIO); ld->sc_dump = ld_virtio_dump; ld->sc_flush = NULL; ld->sc_start = ld_virtio_start; ld->sc_flags = LDF_ENABLED; ldattach(ld); return; err: vsc->sc_child = (void*)1; return; }
static void ld_ataraid_attach(device_t parent, device_t self, void *aux) { struct ld_ataraid_softc *sc = device_private(self); struct ld_softc *ld = &sc->sc_ld; struct ataraid_array_info *aai = aux; struct ataraid_disk_info *adi = NULL; const char *level; struct vnode *vp; char unklev[32]; u_int i; ld->sc_dv = self; if (ld_ataraid_initialized == 0) { ld_ataraid_initialized = 1; pool_init(&ld_ataraid_cbufpl, sizeof(struct cbuf), 0, 0, 0, "ldcbuf", NULL, IPL_BIO); } sc->sc_aai = aai; /* this data persists */ ld->sc_maxxfer = MAXPHYS * aai->aai_width; /* XXX */ ld->sc_secperunit = aai->aai_capacity; ld->sc_secsize = 512; /* XXX */ ld->sc_maxqueuecnt = 128; /* XXX */ ld->sc_dump = ld_ataraid_dump; switch (aai->aai_level) { case AAI_L_SPAN: level = "SPAN"; ld->sc_start = ld_ataraid_start_span; sc->sc_iodone = ld_ataraid_iodone_raid0; break; case AAI_L_RAID0: level = "RAID-0"; ld->sc_start = ld_ataraid_start_raid0; sc->sc_iodone = ld_ataraid_iodone_raid0; break; case AAI_L_RAID1: level = "RAID-1"; ld->sc_start = ld_ataraid_start_raid0; sc->sc_iodone = ld_ataraid_iodone_raid0; break; case AAI_L_RAID0 | AAI_L_RAID1: level = "RAID-10"; ld->sc_start = ld_ataraid_start_raid0; sc->sc_iodone = ld_ataraid_iodone_raid0; break; default: snprintf(unklev, sizeof(unklev), "<unknown level 0x%x>", aai->aai_level); level = unklev; } aprint_naive(": ATA %s array\n", level); aprint_normal(": %s ATA %s array\n", ata_raid_type_name(aai->aai_type), level); if (ld->sc_start == NULL) { aprint_error_dev(ld->sc_dv, "unsupported array type\n"); return; } /* * We get a geometry from the device; use it. */ ld->sc_nheads = aai->aai_heads; ld->sc_nsectors = aai->aai_sectors; ld->sc_ncylinders = aai->aai_cylinders; /* * Configure all the component disks. */ for (i = 0; i < aai->aai_ndisks; i++) { adi = &aai->aai_disks[i]; vp = ata_raid_disk_vnode_find(adi); if (vp == NULL) { /* * XXX This is bogus. We should just mark the * XXX component as FAILED, and write-back new * XXX config blocks. */ break; } sc->sc_vnodes[i] = vp; } if (i == aai->aai_ndisks) { ld->sc_flags = LDF_ENABLED; goto finish; } for (i = 0; i < aai->aai_ndisks; i++) { vp = sc->sc_vnodes[i]; sc->sc_vnodes[i] = NULL; if (vp != NULL) (void) vn_close(vp, FREAD|FWRITE, NOCRED); } finish: #if NBIO > 0 if (bio_register(self, ld_ataraid_bioctl) != 0) panic("%s: bioctl registration failed\n", device_xname(ld->sc_dv)); #endif ldattach(ld); }