Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
0
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);
}
Ejemplo n.º 5
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);
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
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);
}