static void ofdisk_attach(device_t parent, device_t self, void *aux) { struct ofdisk_softc *of = device_private(self); struct ofbus_attach_args *oba = aux; char child[64]; int l; of->sc_dev = self; if ((l = OF_getprop(oba->oba_phandle, "name", child, sizeof child - 1)) < 0) panic("device without name?"); if (l >= sizeof child) l = sizeof child - 1; child[l] = 0; of->sc_flags = 0; of->sc_phandle = oba->oba_phandle; of->sc_unit = oba->oba_unit; of->sc_ihandle = 0; disk_init(&of->sc_dk, device_xname(of->sc_dev), &ofdisk_dkdriver); disk_attach(&of->sc_dk); printf("\n"); if (strcmp(child, "floppy") == 0) of->sc_flags |= OFDF_ISFLOPPY; else { /* Discover wedges on this disk. */ dkwedge_discover(&of->sc_dk); } }
static void md_attach(device_t parent, device_t self, void *aux) { struct md_softc *sc = device_private(self); bufq_alloc(&sc->sc_buflist, "fcfs", 0); /* XXX - Could accept aux info here to set the config. */ #ifdef MEMORY_DISK_HOOKS /* * This external function might setup a pre-loaded disk. * All it would need to do is setup the md_conf struct. * See sys/dev/md_root.c for an example. */ md_attach_hook(device_unit(self), &sc->sc_md); #endif /* * Initialize and attach the disk structure. */ disk_init(&sc->sc_dkdev, device_xname(self), &mddkdriver); disk_attach(&sc->sc_dkdev); if (!pmf_device_register(self, NULL, NULL)) aprint_error_dev(self, "couldn't establish power handler\n"); }
void rlattach(struct device *parent, struct device *self, void *aux) { struct rl_softc *rc = (struct rl_softc *)self; struct rlc_attach_args *ra = aux; struct disklabel *dl; uba_reset_establish(rlreset, self); rc->rc_hwid = ra->hwid; rc->rc_disk.dk_name = rc->rc_dev.dv_xname; disk_attach(&rc->rc_disk); dl = rc->rc_disk.dk_label; dl->d_npartitions = 3; strcpy(dl->d_typename, "RL01"); if (ra->type & RLMP_DT) dl->d_typename[3] = '2'; dl->d_secsize = DEV_BSIZE; /* XXX - wrong, but OK for now */ dl->d_nsectors = RL_SPT/2; dl->d_ntracks = RL_SPD; dl->d_ncylinders = ra->type & RLMP_DT ? RL_TPS02 : RL_TPS01; dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks; dl->d_secperunit = dl->d_ncylinders * dl->d_secpercyl; dl->d_partitions[0].p_size = dl->d_partitions[2].p_size = dl->d_secperunit; dl->d_partitions[0].p_offset = dl->d_partitions[2].p_offset = 0; dl->d_interleave = dl->d_headswitch = 1; dl->d_bbsize = BBSIZE; dl->d_sbsize = SBSIZE; dl->d_rpm = 2400; dl->d_type = DTYPE_DEC; printf(": %s\n", dl->d_typename); }
void rd_attach(struct device *parent, struct device *self, void *aux) { struct rd_softc *sc = (struct rd_softc *)self; /* Attach disk. */ sc->sc_dk.dk_name = sc->sc_dev.dv_xname; disk_attach(&sc->sc_dev, &sc->sc_dk); }
/* * The attach routine only checks and prints drive type. * Bringing the disk online is done when the disk is accessed * the first time. */ void raattach(device_t parent, device_t self, void *aux) { struct rx_softc *rx = device_private(self); struct drive_attach_args *da = aux; struct mscp *mp = da->da_mp; struct mscp_softc *mi = device_private(parent); struct disklabel *dl; rx->ra_dev = self; rx->ra_mediaid = mp->mscp_guse.guse_mediaid; rx->ra_state = DK_CLOSED; rx->ra_hwunit = mp->mscp_unit; mi->mi_dp[mp->mscp_unit] = self; #if NRX if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'X' - '@') disk_init((struct disk *)&rx->ra_disk, device_xname(rx->ra_dev), &rxdkdriver); #endif #if NRACD if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'R' - '@') disk_init((struct disk *)&rx->ra_disk, device_xname(rx->ra_dev), &racddkdriver); #endif #if NRA if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) != 'X' - '@' && MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) != 'R' - '@') disk_init((struct disk *)&rx->ra_disk, device_xname(rx->ra_dev), &radkdriver); #endif disk_attach(&rx->ra_disk); /* Fill in what we know. The actual size is gotten later */ dl = rx->ra_disk.dk_label; dl->d_secsize = DEV_BSIZE; dl->d_nsectors = mp->mscp_guse.guse_nspt; dl->d_ntracks = mp->mscp_guse.guse_ngpc * mp->mscp_guse.guse_group; dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks; disk_printtype(mp->mscp_unit, mp->mscp_guse.guse_mediaid); #ifdef DEBUG printf("%s: nspt %d group %d ngpc %d rct %d nrpt %d nrct %d\n", device_xname(self), mp->mscp_guse.guse_nspt, mp->mscp_guse.guse_group, mp->mscp_guse.guse_ngpc, mp->mscp_guse.guse_rctsize, mp->mscp_guse.guse_nrpt, mp->mscp_guse.guse_nrct); #endif if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) != 'X' - '@') { /* * XXX We should try to discover wedges here, but * XXX that would mean being able to do I/O. Should * XXX use config_defer() here. */ } }
static void ed_mca_attach(device_t parent, device_t self, void *aux) { struct ed_softc *ed = device_private(self); struct edc_mca_softc *sc = device_private(parent); struct ed_attach_args *eda = aux; char pbuf[8]; int drv_flags; ed->sc_dev = self; ed->edc_softc = sc; ed->sc_devno = eda->edc_drive; edc_add_disk(sc, ed); bufq_alloc(&ed->sc_q, "disksort", BUFQ_SORT_RAWBLOCK); mutex_init(&ed->sc_q_lock, MUTEX_DEFAULT, IPL_VM); if (ed_get_params(ed, &drv_flags)) { printf(": IDENTIFY failed, no disk found\n"); return; } format_bytes(pbuf, sizeof(pbuf), (u_int64_t) ed->sc_capacity * DEV_BSIZE); printf(": %s, %u cyl, %u head, %u sec, 512 bytes/sect x %u sectors\n", pbuf, ed->cyl, ed->heads, ed->sectors, ed->sc_capacity); printf("%s: %u spares/cyl, %s, %s, %s, %s, %s\n", device_xname(ed->sc_dev), ed->spares, (drv_flags & (1 << 0)) ? "NoRetries" : "Retries", (drv_flags & (1 << 1)) ? "Removable" : "Fixed", (drv_flags & (1 << 2)) ? "SkewedFormat" : "NoSkew", (drv_flags & (1 << 3)) ? "ZeroDefect" : "Defects", (drv_flags & (1 << 4)) ? "InvalidSecondary" : "SecondaryOK" ); /* * Initialize and attach the disk structure. */ disk_init(&ed->sc_dk, device_xname(ed->sc_dev), &eddkdriver); disk_attach(&ed->sc_dk); rnd_attach_source(&ed->rnd_source, device_xname(ed->sc_dev), RND_TYPE_DISK, RND_FLAG_DEFAULT); ed->sc_flags |= EDF_INIT; /* * XXX We should try to discovery wedges here, but * XXX that would mean being able to do I/O. Should * XXX use config_defer() here. */ }
void mcdattach(struct device *parent, struct device *self, void *aux) { struct mcd_softc *sc = (void *)self; struct isa_attach_args *ia = aux; bus_space_tag_t iot = ia->ia_iot; bus_space_handle_t ioh; struct mcd_mbox mbx; /* Map i/o space */ if (bus_space_map(iot, ia->ia_io[0].ir_addr, MCD_NPORT, 0, &ioh)) { printf(": can't map i/o space\n"); return; } mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); sc->sc_iot = iot; sc->sc_ioh = ioh; sc->probe = 0; sc->debug = 0; if (!mcd_find(iot, ioh, sc)) { printf(": mcd_find failed\n"); return; } bufq_alloc(&sc->buf_queue, "disksort", BUFQ_SORT_RAWBLOCK); callout_init(&sc->sc_pintr_ch, 0); /* * Initialize and attach the disk structure. */ disk_init(&sc->sc_dk, device_xname(&sc->sc_dev), &mcddkdriver); disk_attach(&sc->sc_dk); printf(": model %s\n", sc->type != 0 ? sc->type : "unknown"); (void) mcd_setlock(sc, MCD_LK_UNLOCK); mbx.cmd.opcode = MCD_CMDCONFIGDRIVE; mbx.cmd.length = sizeof(mbx.cmd.data.config) - 1; mbx.cmd.data.config.subcommand = MCD_CF_IRQENABLE; mbx.cmd.data.config.data1 = 0x01; mbx.res.length = 0; (void) mcd_send(sc, &mbx, 0); mcd_soft_reset(sc); sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq, IST_EDGE, IPL_BIO, mcdintr, sc); }
static void bmd_attach(device_t parent, device_t self, void *aux) { struct bmd_softc *sc = device_private(self); struct intio_attach_args *ia = aux; bus_space_tag_t iot = ia->ia_bst; bus_space_handle_t ioh; u_int8_t r; aprint_normal(": Nereid Bank Memory Disk\n"); /* Map I/O space */ ia->ia_size = 2; if (bus_space_map(iot, ia->ia_addr, ia->ia_size, 0, &ioh)) { aprint_error_dev(self, "can't map I/O space\n"); return; } sc->sc_iot = iot; sc->sc_ioh = ioh; /* read control register */ r = bus_space_read_1(sc->sc_iot, sc->sc_ioh, BMD_CTRL); /* check enable-bit */ if ((r & BMD_CTRL_ENABLE) == 0) { aprint_error_dev(self, "disabled by DIP-SW 8\n"); return; } if ((r & BMD_CTRL_MEMORY)) sc->sc_maxpage = 256; else sc->sc_maxpage = 64; if ((r & BMD_CTRL_WINDOW)) sc->sc_window = 0xef0000; else sc->sc_window = 0xee0000; /* Map bank area */ if (bus_space_map(iot, sc->sc_window, BMD_PAGESIZE, 0, &sc->sc_bank)) { aprint_error_dev(self, "can't map bank area: 0x%x\n", sc->sc_window); return; } aprint_normal_dev(self, "%d MB, 0x%x(64KB) x %d pages\n", (sc->sc_maxpage / 16), sc->sc_window, sc->sc_maxpage); disk_init(&sc->sc_dkdev, device_xname(self), &bmddkdriver); disk_attach(&sc->sc_dkdev); }
/* * Allocate the variable sized parts of the softc and * fork the kernel thread. * * The fields sc_clcount, sc_clshift, sc_cache_size and sc_indir_size * must be initialized. */ static int fss_softc_alloc(struct fss_softc *sc) { int i, error; if ((sc->sc_flags & FSS_PERSISTENT) == 0) { sc->sc_copied = kmem_zalloc(howmany(sc->sc_clcount, NBBY), KM_SLEEP); if (sc->sc_copied == NULL) return(ENOMEM); sc->sc_cache = kmem_alloc(sc->sc_cache_size * sizeof(struct fss_cache), KM_SLEEP); if (sc->sc_cache == NULL) return(ENOMEM); for (i = 0; i < sc->sc_cache_size; i++) { sc->sc_cache[i].fc_type = FSS_CACHE_FREE; sc->sc_cache[i].fc_data = kmem_alloc(FSS_CLSIZE(sc), KM_SLEEP); if (sc->sc_cache[i].fc_data == NULL) return(ENOMEM); cv_init(&sc->sc_cache[i].fc_state_cv, "cowwait1"); } sc->sc_indir_valid = kmem_zalloc(howmany(sc->sc_indir_size, NBBY), KM_SLEEP); if (sc->sc_indir_valid == NULL) return(ENOMEM); sc->sc_indir_data = kmem_zalloc(FSS_CLSIZE(sc), KM_SLEEP); if (sc->sc_indir_data == NULL) return(ENOMEM); } else { sc->sc_copied = NULL; sc->sc_cache = NULL; sc->sc_indir_valid = NULL; sc->sc_indir_data = NULL; } sc->sc_flags |= FSS_BS_THREAD; if ((error = kthread_create(PRI_BIO, KTHREAD_MUSTJOIN, NULL, fss_bs_thread, sc, &sc->sc_bs_lwp, "%s", device_xname(sc->sc_dev))) != 0) { sc->sc_flags &= ~FSS_BS_THREAD; return error; } disk_attach(sc->sc_dkdev); return 0; }
void ldattach(struct ld_softc *sc) { char buf[9]; if ((sc->sc_flags & LDF_ENABLED) == 0) { printf("%s: disabled\n", sc->sc_dv.dv_xname); return; } /* Initialise and attach the disk structure. */ sc->sc_dk.dk_driver = &lddkdriver; sc->sc_dk.dk_name = sc->sc_dv.dv_xname; disk_attach(&sc->sc_dk); if (sc->sc_maxxfer > MAXPHYS) sc->sc_maxxfer = MAXPHYS; /* Build synthetic geometry. */ if (sc->sc_secperunit <= 528 * 2048) /* 528MB */ sc->sc_nheads = 16; else if (sc->sc_secperunit <= 1024 * 2048) /* 1GB */ sc->sc_nheads = 32; else if (sc->sc_secperunit <= 21504 * 2048) /* 21GB */ sc->sc_nheads = 64; else if (sc->sc_secperunit <= 43008 * 2048) /* 42GB */ sc->sc_nheads = 128; else sc->sc_nheads = 255; sc->sc_nsectors = 63; sc->sc_ncylinders = sc->sc_secperunit / (sc->sc_nheads * sc->sc_nsectors); format_bytes(buf, sizeof(buf), (u_int64_t)sc->sc_secperunit * sc->sc_secsize); printf("%s: %s, %d cyl, %d head, %d sec, %d bytes/sect x %d sectors\n", sc->sc_dv.dv_xname, buf, sc->sc_ncylinders, sc->sc_nheads, sc->sc_nsectors, sc->sc_secsize, sc->sc_secperunit); #if NRND > 0 /* Attach the device into the rnd source list. */ rnd_attach_source(&sc->sc_rnd_source, sc->sc_dv.dv_xname, RND_TYPE_DISK, 0); #endif /* Set the `shutdownhook'. */ if (ld_sdh == NULL) ld_sdh = shutdownhook_establish(ldshutdown, NULL); BUFQ_INIT(&sc->sc_bufq); }
/* * Controller is working, and drive responded. Attach it. */ void fdattach(device_t parent, device_t self, void *aux) { struct fdc_softc *fdc = device_private(parent); struct fd_softc *fd = device_private(self); struct fdc_attach_args *fa = aux; const struct fd_type *type = fa->fa_deftype; int drive = fa->fa_drive; fd->sc_dev = self; callout_init(&fd->sc_motoron_ch, 0); callout_init(&fd->sc_motoroff_ch, 0); /* XXX Allow `flags' to override device type? */ if (type) aprint_normal(": %s, %d cyl, %d head, %d sec\n", type->name, type->cyls, type->heads, type->sectrac); else aprint_normal(": density unknown\n"); bufq_alloc(&fd->sc_q, "disksort", BUFQ_SORT_CYLINDER); fd->sc_cylin = -1; fd->sc_drive = drive; fd->sc_deftype = type; fdc->sc_fd[drive] = fd; /* * Initialize and attach the disk structure. */ disk_init(&fd->sc_dk, device_xname(fd->sc_dev), &fddkdriver); disk_attach(&fd->sc_dk); /* * Establish a mountroot hook. */ fd->sc_roothook = mountroothook_establish(fd_mountroot_hook, fd->sc_dev); #if NRND > 0 rnd_attach_source(&fd->rnd_source, device_xname(fd->sc_dev), RND_TYPE_DISK, 0); #endif fd_set_properties(fd); if (!pmf_device_register(self, NULL, NULL)) aprint_error_dev(self, "cannot set power mgmt handler\n"); }
static void rdattach(device_t parent, device_t self, void *aux) { struct rd_softc *sc = device_private(self); struct hpibbus_attach_args *ha = aux; sc->sc_dev = self; bufq_alloc(&sc->sc_tab, "disksort", BUFQ_SORT_RAWBLOCK); if (rdident(parent, sc, ha) == 0) { aprint_error(": didn't respond to describe command!\n"); return; } /* * Initialize and attach the disk structure. */ memset(&sc->sc_dkdev, 0, sizeof(sc->sc_dkdev)); disk_init(&sc->sc_dkdev, device_xname(sc->sc_dev), NULL); disk_attach(&sc->sc_dkdev); sc->sc_slave = ha->ha_slave; sc->sc_punit = ha->ha_punit; callout_init(&sc->sc_restart_ch, 0); /* Initialize the hpib job queue entry */ sc->sc_hq.hq_softc = sc; sc->sc_hq.hq_slave = sc->sc_slave; sc->sc_hq.hq_start = rdstart; sc->sc_hq.hq_go = rdgo; sc->sc_hq.hq_intr = rdintr; sc->sc_flags = RDF_ALIVE; #ifdef DEBUG /* always report errors */ if (rddebug & RDB_ERROR) rderrthresh = 0; #endif /* * attach the device into the random source list */ rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), RND_TYPE_DISK, RND_FLAG_DEFAULT); }
/* * The routine called by the low level scsi routine when it discovers * A device suitable for this driver */ void cdattach(struct device *parent, struct device *self, void *aux) { struct scsi_attach_args *sa = aux; struct scsi_link *sc_link = sa->sa_sc_link; struct cd_softc *cd = (struct cd_softc *)self; SC_DEBUG(sc_link, SDEV_DB2, ("cdattach:\n")); /* * Store information needed to contact our base driver */ cd->sc_link = sc_link; sc_link->device = &cd_switch; sc_link->device_softc = cd; if (sc_link->openings > CDOUTSTANDING) sc_link->openings = CDOUTSTANDING; /* * Initialize and attach the disk structure. */ cd->sc_dk.dk_driver = &cddkdriver; cd->sc_dk.dk_name = cd->sc_dev.dv_xname; disk_attach(&cd->sc_dk); /* * Note if this device is ancient. This is used in cdminphys(). */ if (!(sc_link->flags & SDEV_ATAPI) && SCSISPC(sa->sa_inqbuf->version) == 0) cd->flags |= CDF_ANCIENT; printf("\n"); timeout_set(&cd->sc_timeout, cdrestart, cd); if ((cd->sc_cdpwrhook = powerhook_establish(cd_powerhook, cd)) == NULL) printf("%s: WARNING: unable to establish power hook\n", cd->sc_dev.dv_xname); }
void rlattach(device_t parent, device_t self, void *aux) { struct rl_softc *rc = device_private(self); struct rlc_attach_args *ra = aux; struct disklabel *dl; rc->rc_dev = self; rc->rc_rlc = device_private(parent); rc->rc_hwid = ra->hwid; disk_init(&rc->rc_disk, device_xname(rc->rc_dev), &rldkdriver); disk_attach(&rc->rc_disk); dl = rc->rc_disk.dk_label; dl->d_npartitions = 3; strcpy(dl->d_typename, "RL01"); if (ra->type & RLMP_DT) dl->d_typename[3] = '2'; dl->d_secsize = DEV_BSIZE; /* XXX - wrong, but OK for now */ dl->d_nsectors = RL_SPT/2; dl->d_ntracks = RL_SPD; dl->d_ncylinders = ra->type & RLMP_DT ? RL_TPS02 : RL_TPS01; dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks; dl->d_secperunit = dl->d_ncylinders * dl->d_secpercyl; dl->d_partitions[0].p_size = dl->d_partitions[2].p_size = dl->d_secperunit; dl->d_partitions[0].p_offset = dl->d_partitions[2].p_offset = 0; dl->d_interleave = dl->d_headswitch = 1; dl->d_bbsize = BBSIZE; dl->d_sbsize = SBLOCKSIZE; dl->d_rpm = 2400; dl->d_type = DTYPE_DEC; printf(": %s, %s\n", dl->d_typename, rlstate(rc->rc_rlc, ra->hwid)); /* * XXX We should try to discovery wedges here, but * XXX that would mean loading up the pack and being * XXX able to do I/O. Should use config_defer() here. */ }
void rdattach(device_t parent, device_t self, void *aux) { struct hdcsoftc * const sc = device_private(parent); struct rdsoftc * const rd = device_private(self); struct hdc_attach_args * const ha = aux; struct disklabel *dl; const char *msg; rd->sc_dev = self; rd->sc_drive = ha->ha_drive; rd->sc_hdc = sc; /* * Initialize and attach the disk structure. */ disk_init(&rd->sc_disk, device_xname(rd->sc_dev), NULL); disk_attach(&rd->sc_disk); /* * if it's not a floppy then evaluate the on-disk geometry. * if necessary correct the label... */ rd_readgeom(sc, rd); disk_printtype(rd->sc_drive, rd->sc_xbn.media_id); dl = rd->sc_disk.dk_label; rdmakelabel(dl, &rd->sc_xbn); msg = readdisklabel(MAKEDISKDEV(cdevsw_lookup_major(&rd_cdevsw), device_unit(rd->sc_dev), RAW_PART), rdstrategy, dl, NULL); if (msg) aprint_normal_dev(self, "%s: size %u sectors", msg, dl->d_secperunit); else aprint_normal_dev(self, "size %u sectors\n", dl->d_secperunit); #ifdef RDDEBUG hdc_printgeom(&rd->sc_xbn); #endif }
/* * Create in-kernel entry for device. Device attributes such as name, uuid are * taken from proplib dictionary. * */ int dm_dev_create_ioctl(prop_dictionary_t dm_dict) { dm_dev_t *dmv; const char *name, *uuid; int r, flags; device_t devt; r = 0; flags = 0; name = NULL; uuid = NULL; /* Get needed values from dictionary. */ prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_NAME, &name); prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_UUID, &uuid); prop_dictionary_get_uint32(dm_dict, DM_IOCTL_FLAGS, &flags); dm_dbg_print_flags(flags); /* Lookup name and uuid if device already exist quit. */ if ((dmv = dm_dev_lookup(name, uuid, -1)) != NULL) { DM_ADD_FLAG(flags, DM_EXISTS_FLAG); /* Device already exists */ dm_dev_unbusy(dmv); return EEXIST; } if ((devt = config_attach_pseudo(&dm_cfdata)) == NULL) { aprint_error("Unable to attach pseudo device dm/%s\n", name); return (ENOMEM); } if ((dmv = dm_dev_alloc()) == NULL) return ENOMEM; if (uuid) strncpy(dmv->uuid, uuid, DM_UUID_LEN); else dmv->uuid[0] = '\0'; if (name) strlcpy(dmv->name, name, DM_NAME_LEN); dmv->minor = (uint64_t)atomic_inc_32_nv(&sc_minor_num); dmv->flags = 0; /* device flags are set when needed */ dmv->ref_cnt = 0; dmv->event_nr = 0; dmv->dev_type = 0; dmv->devt = devt; dm_table_head_init(&dmv->table_head); mutex_init(&dmv->dev_mtx, MUTEX_DEFAULT, IPL_NONE); mutex_init(&dmv->diskp_mtx, MUTEX_DEFAULT, IPL_NONE); cv_init(&dmv->dev_cv, "dm_dev"); if (flags & DM_READONLY_FLAG) dmv->flags |= DM_READONLY_FLAG; prop_dictionary_set_uint32(dm_dict, DM_IOCTL_MINOR, dmv->minor); disk_init(dmv->diskp, dmv->name, &dmdkdriver); disk_attach(dmv->diskp); dmv->diskp->dk_info = NULL; if ((r = dm_dev_insert(dmv)) != 0) dm_dev_free(dmv); DM_ADD_FLAG(flags, DM_EXISTS_FLAG); DM_REMOVE_FLAG(flags, DM_INACTIVE_PRESENT_FLAG); /* Increment device counter After creating device */ atomic_inc_32(&dm_dev_counter); return r; }
/* * Controller is working, and drive responded. Attach it. */ void fdattach(struct device *parent, struct device *self, void *aux) { struct fdc_softc *fdc = (void *)parent; struct fd_softc *fd = (void *)self; struct fdc_attach_args *fa = aux; struct fd_type *type = fa->fa_deftype; int drive = fa->fa_drive; if (!type || (fa->fa_flags & 0x10)) { /* The config has overridden this. */ switch (fa->fa_flags & 0x07) { case 1: /* 2.88MB */ type = &fd_types[7]; break; case 2: /* 1.44MB */ type = &fd_types[0]; break; case 3: /* 1.2MB */ type = &fd_types[1]; break; case 4: /* 720K */ type = &fd_types[4]; break; case 5: /* 360K */ type = &fd_types[3]; break; case 6: /* 1.2 MB japanese format */ type = &fd_types[8]; break; #ifdef __alpha__ default: /* 1.44MB, how to detect others? * idea from NetBSD -- [email protected] */ type = &fd_types[0]; #endif } } if (type) printf(": %s %d cyl, %d head, %d sec\n", type->name, type->tracks, type->heads, type->sectrac); else printf(": density unknown\n"); fd->sc_cylin = -1; fd->sc_drive = drive; fd->sc_deftype = type; fdc->sc_type[drive] = FDC_TYPE_DISK; fdc->sc_link.fdlink.sc_fd[drive] = fd; /* * Initialize and attach the disk structure. */ fd->sc_dk.dk_flags = DKF_NOLABELREAD; fd->sc_dk.dk_name = fd->sc_dev.dv_xname; bufq_init(&fd->sc_bufq, BUFQ_DEFAULT); disk_attach(&fd->sc_dev, &fd->sc_dk); /* Setup timeout structures */ timeout_set(&fd->fd_motor_on_to, fd_motor_on, fd); timeout_set(&fd->fd_motor_off_to, fd_motor_off, fd); timeout_set(&fd->fdtimeout_to, fdtimeout, fd); }
/* ARGSUSED */ static int vndioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) { bool force; int unit = vndunit(dev); struct vnd_softc *vnd; struct vnd_ioctl *vio; struct vattr vattr; struct pathbuf *pb; struct nameidata nd; int error, part, pmask; uint64_t geomsize; int fflags; #ifdef __HAVE_OLD_DISKLABEL struct disklabel newlabel; #endif struct dkwedge_info *dkw; struct dkwedge_list *dkwl; #ifdef DEBUG if (vnddebug & VDB_FOLLOW) printf("vndioctl(0x%"PRIx64", 0x%lx, %p, 0x%x, %p): unit %d\n", dev, cmd, data, flag, l->l_proc, unit); #endif vnd = device_lookup_private(&vnd_cd, unit); if (vnd == NULL && #ifdef COMPAT_30 cmd != VNDIOCGET30 && #endif #ifdef COMPAT_50 cmd != VNDIOCGET50 && #endif cmd != VNDIOCGET) return ENXIO; vio = (struct vnd_ioctl *)data; /* Must be open for writes for these commands... */ switch (cmd) { case VNDIOCSET: case VNDIOCCLR: #ifdef COMPAT_50 case VNDIOCSET50: case VNDIOCCLR50: #endif case DIOCSDINFO: case DIOCWDINFO: #ifdef __HAVE_OLD_DISKLABEL case ODIOCSDINFO: case ODIOCWDINFO: #endif case DIOCKLABEL: case DIOCWLABEL: if ((flag & FWRITE) == 0) return EBADF; } /* Must be initialized for these... */ switch (cmd) { case VNDIOCCLR: #ifdef VNDIOCCLR50 case VNDIOCCLR50: #endif case DIOCGDINFO: case DIOCSDINFO: case DIOCWDINFO: case DIOCGPART: case DIOCKLABEL: case DIOCWLABEL: case DIOCGDEFLABEL: case DIOCCACHESYNC: #ifdef __HAVE_OLD_DISKLABEL case ODIOCGDINFO: case ODIOCSDINFO: case ODIOCWDINFO: case ODIOCGDEFLABEL: #endif if ((vnd->sc_flags & VNF_INITED) == 0) return ENXIO; } switch (cmd) { #ifdef VNDIOCSET50 case VNDIOCSET50: #endif case VNDIOCSET: if (vnd->sc_flags & VNF_INITED) return EBUSY; if ((error = vndlock(vnd)) != 0) return error; fflags = FREAD; if ((vio->vnd_flags & VNDIOF_READONLY) == 0) fflags |= FWRITE; error = pathbuf_copyin(vio->vnd_file, &pb); if (error) { goto unlock_and_exit; } NDINIT(&nd, LOOKUP, FOLLOW, pb); if ((error = vn_open(&nd, fflags, 0)) != 0) { pathbuf_destroy(pb); goto unlock_and_exit; } KASSERT(l); error = VOP_GETATTR(nd.ni_vp, &vattr, l->l_cred); if (!error && nd.ni_vp->v_type != VREG) error = EOPNOTSUPP; if (!error && vattr.va_bytes < vattr.va_size) /* File is definitely sparse, use vn_rdwr() */ vnd->sc_flags |= VNF_USE_VN_RDWR; if (error) { VOP_UNLOCK(nd.ni_vp); goto close_and_exit; } /* If using a compressed file, initialize its info */ /* (or abort with an error if kernel has no compression) */ if (vio->vnd_flags & VNF_COMP) { #ifdef VND_COMPRESSION struct vnd_comp_header *ch; int i; u_int32_t comp_size; u_int32_t comp_maxsize; /* allocate space for compresed file header */ ch = malloc(sizeof(struct vnd_comp_header), M_TEMP, M_WAITOK); /* read compressed file header */ error = vn_rdwr(UIO_READ, nd.ni_vp, (void *)ch, sizeof(struct vnd_comp_header), 0, UIO_SYSSPACE, IO_UNIT|IO_NODELOCKED, l->l_cred, NULL, NULL); if (error) { free(ch, M_TEMP); VOP_UNLOCK(nd.ni_vp); goto close_and_exit; } /* save some header info */ vnd->sc_comp_blksz = ntohl(ch->block_size); /* note last offset is the file byte size */ vnd->sc_comp_numoffs = ntohl(ch->num_blocks)+1; free(ch, M_TEMP); if (vnd->sc_comp_blksz == 0 || vnd->sc_comp_blksz % DEV_BSIZE !=0) { VOP_UNLOCK(nd.ni_vp); error = EINVAL; goto close_and_exit; } if (sizeof(struct vnd_comp_header) + sizeof(u_int64_t) * vnd->sc_comp_numoffs > vattr.va_size) { VOP_UNLOCK(nd.ni_vp); error = EINVAL; goto close_and_exit; } /* set decompressed file size */ vattr.va_size = ((u_quad_t)vnd->sc_comp_numoffs - 1) * (u_quad_t)vnd->sc_comp_blksz; /* allocate space for all the compressed offsets */ vnd->sc_comp_offsets = malloc(sizeof(u_int64_t) * vnd->sc_comp_numoffs, M_DEVBUF, M_WAITOK); /* read in the offsets */ error = vn_rdwr(UIO_READ, nd.ni_vp, (void *)vnd->sc_comp_offsets, sizeof(u_int64_t) * vnd->sc_comp_numoffs, sizeof(struct vnd_comp_header), UIO_SYSSPACE, IO_UNIT|IO_NODELOCKED, l->l_cred, NULL, NULL); if (error) { VOP_UNLOCK(nd.ni_vp); goto close_and_exit; } /* * find largest block size (used for allocation limit). * Also convert offset to native byte order. */ comp_maxsize = 0; for (i = 0; i < vnd->sc_comp_numoffs - 1; i++) { vnd->sc_comp_offsets[i] = be64toh(vnd->sc_comp_offsets[i]); comp_size = be64toh(vnd->sc_comp_offsets[i + 1]) - vnd->sc_comp_offsets[i]; if (comp_size > comp_maxsize) comp_maxsize = comp_size; } vnd->sc_comp_offsets[vnd->sc_comp_numoffs - 1] = be64toh(vnd->sc_comp_offsets[vnd->sc_comp_numoffs - 1]); /* create compressed data buffer */ vnd->sc_comp_buff = malloc(comp_maxsize, M_DEVBUF, M_WAITOK); /* create decompressed buffer */ vnd->sc_comp_decombuf = malloc(vnd->sc_comp_blksz, M_DEVBUF, M_WAITOK); vnd->sc_comp_buffblk = -1; /* Initialize decompress stream */ memset(&vnd->sc_comp_stream, 0, sizeof(z_stream)); vnd->sc_comp_stream.zalloc = vnd_alloc; vnd->sc_comp_stream.zfree = vnd_free; error = inflateInit2(&vnd->sc_comp_stream, MAX_WBITS); if (error) { if (vnd->sc_comp_stream.msg) printf("vnd%d: compressed file, %s\n", unit, vnd->sc_comp_stream.msg); VOP_UNLOCK(nd.ni_vp); error = EINVAL; goto close_and_exit; } vnd->sc_flags |= VNF_COMP | VNF_READONLY; #else /* !VND_COMPRESSION */ VOP_UNLOCK(nd.ni_vp); error = EOPNOTSUPP; goto close_and_exit; #endif /* VND_COMPRESSION */ } VOP_UNLOCK(nd.ni_vp); vnd->sc_vp = nd.ni_vp; vnd->sc_size = btodb(vattr.va_size); /* note truncation */ /* * Use pseudo-geometry specified. If none was provided, * use "standard" Adaptec fictitious geometry. */ if (vio->vnd_flags & VNDIOF_HASGEOM) { memcpy(&vnd->sc_geom, &vio->vnd_geom, sizeof(vio->vnd_geom)); /* * Sanity-check the sector size. * XXX Don't allow secsize < DEV_BSIZE. Should * XXX we? */ if (vnd->sc_geom.vng_secsize < DEV_BSIZE || (vnd->sc_geom.vng_secsize % DEV_BSIZE) != 0 || vnd->sc_geom.vng_ncylinders == 0 || (vnd->sc_geom.vng_ntracks * vnd->sc_geom.vng_nsectors) == 0) { error = EINVAL; goto close_and_exit; } /* * Compute the size (in DEV_BSIZE blocks) specified * by the geometry. */ geomsize = (vnd->sc_geom.vng_nsectors * vnd->sc_geom.vng_ntracks * vnd->sc_geom.vng_ncylinders) * (vnd->sc_geom.vng_secsize / DEV_BSIZE); /* * Sanity-check the size against the specified * geometry. */ if (vnd->sc_size < geomsize) { error = EINVAL; goto close_and_exit; } } else if (vnd->sc_size >= (32 * 64)) { /* * Size must be at least 2048 DEV_BSIZE blocks * (1M) in order to use this geometry. */ vnd->sc_geom.vng_secsize = DEV_BSIZE; vnd->sc_geom.vng_nsectors = 32; vnd->sc_geom.vng_ntracks = 64; vnd->sc_geom.vng_ncylinders = vnd->sc_size / (64 * 32); } else { vnd->sc_geom.vng_secsize = DEV_BSIZE; vnd->sc_geom.vng_nsectors = 1; vnd->sc_geom.vng_ntracks = 1; vnd->sc_geom.vng_ncylinders = vnd->sc_size; } vnd_set_geometry(vnd); if (vio->vnd_flags & VNDIOF_READONLY) { vnd->sc_flags |= VNF_READONLY; } if ((error = vndsetcred(vnd, l->l_cred)) != 0) goto close_and_exit; vndthrottle(vnd, vnd->sc_vp); vio->vnd_osize = dbtob(vnd->sc_size); #ifdef VNDIOCSET50 if (cmd != VNDIOCSET50) #endif vio->vnd_size = dbtob(vnd->sc_size); vnd->sc_flags |= VNF_INITED; /* create the kernel thread, wait for it to be up */ error = kthread_create(PRI_NONE, 0, NULL, vndthread, vnd, &vnd->sc_kthread, "%s", device_xname(vnd->sc_dev)); if (error) goto close_and_exit; while ((vnd->sc_flags & VNF_KTHREAD) == 0) { tsleep(&vnd->sc_kthread, PRIBIO, "vndthr", 0); } #ifdef DEBUG if (vnddebug & VDB_INIT) printf("vndioctl: SET vp %p size 0x%lx %d/%d/%d/%d\n", vnd->sc_vp, (unsigned long) vnd->sc_size, vnd->sc_geom.vng_secsize, vnd->sc_geom.vng_nsectors, vnd->sc_geom.vng_ntracks, vnd->sc_geom.vng_ncylinders); #endif /* Attach the disk. */ disk_attach(&vnd->sc_dkdev); disk_blocksize(&vnd->sc_dkdev, vnd->sc_geom.vng_secsize); /* Initialize the xfer and buffer pools. */ pool_init(&vnd->sc_vxpool, sizeof(struct vndxfer), 0, 0, 0, "vndxpl", NULL, IPL_BIO); vndunlock(vnd); pathbuf_destroy(pb); /* Discover wedges on this disk */ dkwedge_discover(&vnd->sc_dkdev); break; close_and_exit: (void) vn_close(nd.ni_vp, fflags, l->l_cred); pathbuf_destroy(pb); unlock_and_exit: #ifdef VND_COMPRESSION /* free any allocated memory (for compressed file) */ if (vnd->sc_comp_offsets) { free(vnd->sc_comp_offsets, M_DEVBUF); vnd->sc_comp_offsets = NULL; } if (vnd->sc_comp_buff) { free(vnd->sc_comp_buff, M_DEVBUF); vnd->sc_comp_buff = NULL; } if (vnd->sc_comp_decombuf) { free(vnd->sc_comp_decombuf, M_DEVBUF); vnd->sc_comp_decombuf = NULL; } #endif /* VND_COMPRESSION */ vndunlock(vnd); return error; #ifdef VNDIOCCLR50 case VNDIOCCLR50: #endif case VNDIOCCLR: part = DISKPART(dev); pmask = (1 << part); force = (vio->vnd_flags & VNDIOF_FORCE) != 0; if ((error = vnddoclear(vnd, pmask, minor(dev), force)) != 0) return error; break; #ifdef COMPAT_30 case VNDIOCGET30: { struct vnd_user30 *vnu; struct vattr va; vnu = (struct vnd_user30 *)data; KASSERT(l); switch (error = vnd_cget(l, unit, &vnu->vnu_unit, &va)) { case 0: vnu->vnu_dev = va.va_fsid; vnu->vnu_ino = va.va_fileid; break; case -1: /* unused is not an error */ vnu->vnu_dev = 0; vnu->vnu_ino = 0; break; default: return error; } break; } #endif #ifdef COMPAT_50 case VNDIOCGET50: { struct vnd_user50 *vnu; struct vattr va; vnu = (struct vnd_user50 *)data; KASSERT(l); switch (error = vnd_cget(l, unit, &vnu->vnu_unit, &va)) { case 0: vnu->vnu_dev = va.va_fsid; vnu->vnu_ino = va.va_fileid; break; case -1: /* unused is not an error */ vnu->vnu_dev = 0; vnu->vnu_ino = 0; break; default: return error; } break; } #endif case VNDIOCGET: { struct vnd_user *vnu; struct vattr va; vnu = (struct vnd_user *)data; KASSERT(l); switch (error = vnd_cget(l, unit, &vnu->vnu_unit, &va)) { case 0: vnu->vnu_dev = va.va_fsid; vnu->vnu_ino = va.va_fileid; break; case -1: /* unused is not an error */ vnu->vnu_dev = 0; vnu->vnu_ino = 0; break; default: return error; } break; } case DIOCGDINFO: *(struct disklabel *)data = *(vnd->sc_dkdev.dk_label); break; #ifdef __HAVE_OLD_DISKLABEL case ODIOCGDINFO: newlabel = *(vnd->sc_dkdev.dk_label); if (newlabel.d_npartitions > OLDMAXPARTITIONS) return ENOTTY; memcpy(data, &newlabel, sizeof (struct olddisklabel)); break; #endif case DIOCGPART: ((struct partinfo *)data)->disklab = vnd->sc_dkdev.dk_label; ((struct partinfo *)data)->part = &vnd->sc_dkdev.dk_label->d_partitions[DISKPART(dev)]; break; case DIOCWDINFO: case DIOCSDINFO: #ifdef __HAVE_OLD_DISKLABEL case ODIOCWDINFO: case ODIOCSDINFO: #endif { struct disklabel *lp; if ((error = vndlock(vnd)) != 0) return error; vnd->sc_flags |= VNF_LABELLING; #ifdef __HAVE_OLD_DISKLABEL if (cmd == ODIOCSDINFO || cmd == ODIOCWDINFO) { memset(&newlabel, 0, sizeof newlabel); memcpy(&newlabel, data, sizeof (struct olddisklabel)); lp = &newlabel; } else #endif lp = (struct disklabel *)data; error = setdisklabel(vnd->sc_dkdev.dk_label, lp, 0, vnd->sc_dkdev.dk_cpulabel); if (error == 0) { if (cmd == DIOCWDINFO #ifdef __HAVE_OLD_DISKLABEL || cmd == ODIOCWDINFO #endif ) error = writedisklabel(VNDLABELDEV(dev), vndstrategy, vnd->sc_dkdev.dk_label, vnd->sc_dkdev.dk_cpulabel); } vnd->sc_flags &= ~VNF_LABELLING; vndunlock(vnd); if (error) return error; break; } case DIOCKLABEL: if (*(int *)data != 0) vnd->sc_flags |= VNF_KLABEL; else vnd->sc_flags &= ~VNF_KLABEL; break; case DIOCWLABEL: if (*(int *)data != 0) vnd->sc_flags |= VNF_WLABEL; else vnd->sc_flags &= ~VNF_WLABEL; break; case DIOCGDEFLABEL: vndgetdefaultlabel(vnd, (struct disklabel *)data); break; #ifdef __HAVE_OLD_DISKLABEL case ODIOCGDEFLABEL: vndgetdefaultlabel(vnd, &newlabel); if (newlabel.d_npartitions > OLDMAXPARTITIONS) return ENOTTY; memcpy(data, &newlabel, sizeof (struct olddisklabel)); break; #endif case DIOCCACHESYNC: vn_lock(vnd->sc_vp, LK_EXCLUSIVE | LK_RETRY); error = VOP_FSYNC(vnd->sc_vp, vnd->sc_cred, FSYNC_WAIT | FSYNC_DATAONLY | FSYNC_CACHE, 0, 0); VOP_UNLOCK(vnd->sc_vp); return error; case DIOCAWEDGE: dkw = (void *) data; if ((flag & FWRITE) == 0) return EBADF; /* If the ioctl happens here, the parent is us. */ strlcpy(dkw->dkw_parent, device_xname(vnd->sc_dev), sizeof(dkw->dkw_parent)); return dkwedge_add(dkw); case DIOCDWEDGE: dkw = (void *) data; if ((flag & FWRITE) == 0) return EBADF; /* If the ioctl happens here, the parent is us. */ strlcpy(dkw->dkw_parent, device_xname(vnd->sc_dev), sizeof(dkw->dkw_parent)); return dkwedge_del(dkw); case DIOCLWEDGES: dkwl = (void *) data; return dkwedge_list(&vnd->sc_dkdev, dkwl, l); default: return ENOTTY; } return 0; }
/* * The routine called by the low level scsi routine when it discovers * a device suitable for this driver. */ void sdattach(struct device *parent, struct device *self, void *aux) { struct sd_softc *sc = (struct sd_softc *)self; struct scsi_attach_args *sa = aux; struct disk_parms *dp = &sc->params; struct scsi_link *sc_link = sa->sa_sc_link; int sd_autoconf = scsi_autoconf | SCSI_SILENT | SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE; struct dk_cache dkc; int error, result; SC_DEBUG(sc_link, SDEV_DB2, ("sdattach:\n")); /* * Store information needed to contact our base driver */ sc->sc_link = sc_link; sc_link->interpret_sense = sd_interpret_sense; sc_link->device_softc = sc; if ((sc_link->flags & SDEV_ATAPI) && (sc_link->flags & SDEV_REMOVABLE)) sc_link->quirks |= SDEV_NOSYNCCACHE; if (!(sc_link->inqdata.flags & SID_RelAdr)) sc_link->quirks |= SDEV_ONLYBIG; /* * Note if this device is ancient. This is used in sdminphys(). */ if (!(sc_link->flags & SDEV_ATAPI) && SCSISPC(sa->sa_inqbuf->version) == 0) sc->flags |= SDF_ANCIENT; /* * Use the subdriver to request information regarding * the drive. We cannot use interrupts yet, so the * request must specify this. */ printf("\n"); scsi_xsh_set(&sc->sc_xsh, sc_link, sdstart); timeout_set(&sc->sc_timeout, (void (*)(void *))scsi_xsh_add, &sc->sc_xsh); /* Spin up non-UMASS devices ready or not. */ if ((sc->sc_link->flags & SDEV_UMASS) == 0) scsi_start(sc_link, SSS_START, sd_autoconf); /* * Some devices (e.g. Blackberry Pearl) won't admit they have * media loaded unless its been locked in. */ if ((sc_link->flags & SDEV_REMOVABLE) != 0) scsi_prevent(sc_link, PR_PREVENT, sd_autoconf); /* Check that it is still responding and ok. */ error = scsi_test_unit_ready(sc->sc_link, TEST_READY_RETRIES * 3, sd_autoconf); if (error) result = SDGP_RESULT_OFFLINE; else result = sd_get_parms(sc, &sc->params, sd_autoconf); if ((sc_link->flags & SDEV_REMOVABLE) != 0) scsi_prevent(sc_link, PR_ALLOW, sd_autoconf); switch (result) { case SDGP_RESULT_OK: printf("%s: %lluMB, %lu bytes/sector, %llu sectors", sc->sc_dev.dv_xname, dp->disksize / (1048576 / dp->secsize), dp->secsize, dp->disksize); printf("\n"); break; case SDGP_RESULT_OFFLINE: break; #ifdef DIAGNOSTIC default: panic("sdattach: unknown result (%#x) from get_parms", result); break; #endif } /* * Initialize disk structures. */ sc->sc_dk.dk_name = sc->sc_dev.dv_xname; bufq_init(&sc->sc_bufq, BUFQ_FIFO); /* * Enable write cache by default. */ memset(&dkc, 0, sizeof(dkc)); if (sd_ioctl_cache(sc, DIOCGCACHE, &dkc) == 0 && dkc.wrcache == 0) { dkc.wrcache = 1; sd_ioctl_cache(sc, DIOCSCACHE, &dkc); } /* * Establish a shutdown hook so that we can ensure that * our data has actually made it onto the platter at * shutdown time. Note that this relies on the fact * that the shutdown hook code puts us at the head of * the list (thus guaranteeing that our hook runs before * our ancestors'). */ if ((sc->sc_sdhook = shutdownhook_establish(sd_shutdown, sc)) == NULL) printf("%s: WARNING: unable to establish shutdown hook\n", sc->sc_dev.dv_xname); /* Attach disk. */ disk_attach(&sc->sc_dev, &sc->sc_dk); }
int maruioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { ENTERSC(dev); DB("maruioctl(%d, %ld, %p, %d, %p)\n", dev, cmd, data, flag, p); switch (cmd) { case MARUIOCATTACH: { struct maru_ioc_attach *ma = (struct maru_ioc_attach *)data; int fd = ma->ma_kue_fd; struct filedesc *fdp = p->p_fd; struct file *fp; int err; struct stat st; struct kue_kapi *kapi; if (ma->ma_size < 512 * 16 * 32) EXITSC(EINVAL); if (fd>=fdp->fd_nfiles || (fp=fdp->fd_ofiles[fd]) == NULL) EXITSC(EBADF); if (fp->f_type != DTYPE_VNODE) EXITSC(ENOENT); /* some fool handed us a socket */ /* ok, so, this is cheating a little :) */ err = vn_stat((struct vnode *)fp->f_data, &st, p); if (err) EXITSC(err); /* pull in a pointer to the kue kernel api. we need * this hack in order to avoid nasty limitations in netbsd's * kernel linker: symbols from one module * are not linked against symbols from another, only * the kernel image. we splinter a little wood */ err = fp->f_ops->fo_ioctl(fp, KUEIOCGKAPI, (caddr_t)&kapi, p); DB("post ioctl"); if (err) EXITSC(err); DB("post ioctl:2"); /* now install our hooks of evil */ sc->sc_kapi = kapi; DB("post ioctl:3"); kapi->ka_read2_hook = maru_kue_read2_callback; DB("post ioctl:4"); kapi->ka_free_hook = maru_kue_free_callback; kapi->ka_write_hook = maru_kue_write_callback; disk_attach(&sc->sc_dkdev); memcpy(&sc->sc_size, &ma->ma_size, sizeof sc->sc_size); sc->sc_flags|=MUF_INITED; maru_getdisklabel(sc); } break; case DIOCGDINFO: maru_getdefaultlabel(sc, (struct disklabel*)data); break; case DIOCGPART: ((struct partinfo *)data)->disklab = sc->sc_dkdev.dk_label; ((struct partinfo *)data)->part = &sc->sc_dkdev.dk_label->d_partitions[DISKPART(dev)]; break; case DIOCWDINFO: case DIOCSDINFO: { int err; sc->sc_flags |= MUF_LABELING; /* marustrategy maybe called by writedisklabel() */ err = setdisklabel(sc->sc_dkdev.dk_label, (struct disklabel *)data, 0, sc->sc_dkdev.dk_cpulabel); if (!err) { if (cmd == DIOCWDINFO) err = writedisklabel(MARULABELDEV(dev), marustrategy, sc->sc_dkdev.dk_label, sc->sc_dkdev.dk_cpulabel); } sc->sc_flags &= ~MUF_LABELING; if (err) EXITSC(err); } break; case DIOCWLABEL: if (*(int *)data != 0) sc->sc_flags |= MUF_WLABEL; else sc->sc_flags &= ~MUF_WLABEL; break; case DIOCGDEFLABEL: maru_getdefaultlabel(sc, (struct disklabel*)data); break; default: return (ENOTTY); } EXITSC(0); }
void wdattach(struct device *parent, struct device *self, void *aux) { struct wd_softc *wd = (void *)self; struct ata_atapi_attach *aa_link= aux; struct wdc_command wdc_c; int i, blank; char buf[41], c, *p, *q; WDCDEBUG_PRINT(("wdattach\n"), DEBUG_FUNCS | DEBUG_PROBE); wd->openings = aa_link->aa_openings; wd->drvp = aa_link->aa_drv_data; strlcpy(wd->drvp->drive_name, wd->sc_dev.dv_xname, sizeof(wd->drvp->drive_name)); wd->drvp->cf_flags = wd->sc_dev.dv_cfdata->cf_flags; if ((NERRS_MAX - 2) > 0) wd->drvp->n_dmaerrs = NERRS_MAX - 2; else wd->drvp->n_dmaerrs = 0; /* read our drive info */ if (wd_get_params(wd, at_poll, &wd->sc_params) != 0) { printf("%s: IDENTIFY failed\n", wd->sc_dev.dv_xname); return; } for (blank = 0, p = wd->sc_params.atap_model, q = buf, i = 0; i < sizeof(wd->sc_params.atap_model); i++) { c = *p++; if (c == '\0') break; if (c != ' ') { if (blank) { *q++ = ' '; blank = 0; } *q++ = c; } else blank = 1; } *q++ = '\0'; printf(": <%s>\n", buf); wdc_probe_caps(wd->drvp, &wd->sc_params); wdc_print_caps(wd->drvp); if ((wd->sc_params.atap_multi & 0xff) > 1) { wd->sc_multi = wd->sc_params.atap_multi & 0xff; } else { wd->sc_multi = 1; } printf("%s: %d-sector PIO,", wd->sc_dev.dv_xname, wd->sc_multi); /* use 48-bit LBA if enabled */ /* XXX: shall we use it if drive capacity < 137Gb? */ if ((wd->sc_params.atap_cmd2_en & ATAPI_CMD2_48AD) != 0) wd->sc_flags |= WDF_LBA48; /* Prior to ATA-4, LBA was optional. */ if ((wd->sc_params.atap_capabilities1 & WDC_CAP_LBA) != 0) wd->sc_flags |= WDF_LBA; #if 0 /* ATA-4 requires LBA. */ if (wd->sc_params.atap_ataversion != 0xffff && wd->sc_params.atap_ataversion >= WDC_VER_ATA4) wd->sc_flags |= WDF_LBA; #endif if ((wd->sc_flags & WDF_LBA48) != 0) { wd->sc_capacity = (((u_int64_t)wd->sc_params.atap_max_lba[3] << 48) | ((u_int64_t)wd->sc_params.atap_max_lba[2] << 32) | ((u_int64_t)wd->sc_params.atap_max_lba[1] << 16) | (u_int64_t)wd->sc_params.atap_max_lba[0]); printf(" LBA48, %lluMB, %llu sectors\n", wd->sc_capacity / (1048576 / DEV_BSIZE), wd->sc_capacity); } else if ((wd->sc_flags & WDF_LBA) != 0) { wd->sc_capacity = (wd->sc_params.atap_capacity[1] << 16) | wd->sc_params.atap_capacity[0]; printf(" LBA, %lluMB, %llu sectors\n", wd->sc_capacity / (1048576 / DEV_BSIZE), wd->sc_capacity); } else { wd->sc_capacity = wd->sc_params.atap_cylinders * wd->sc_params.atap_heads * wd->sc_params.atap_sectors; printf(" CHS, %lluMB, %d cyl, %d head, %d sec, %llu sectors\n", wd->sc_capacity / (1048576 / DEV_BSIZE), wd->sc_params.atap_cylinders, wd->sc_params.atap_heads, wd->sc_params.atap_sectors, wd->sc_capacity); } WDCDEBUG_PRINT(("%s: atap_dmatiming_mimi=%d, atap_dmatiming_recom=%d\n", self->dv_xname, wd->sc_params.atap_dmatiming_mimi, wd->sc_params.atap_dmatiming_recom), DEBUG_PROBE); /* use read look ahead if supported */ if (wd->sc_params.atap_cmd_set1 & WDC_CMD1_AHEAD) { bzero(&wdc_c, sizeof(struct wdc_command)); wdc_c.r_command = SET_FEATURES; wdc_c.r_precomp = WDSF_READAHEAD_EN; wdc_c.timeout = 1000; wdc_c.flags = at_poll; if (wdc_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) { printf("%s: enable look ahead command didn't " "complete\n", wd->sc_dev.dv_xname); } } /* use write cache if supported */ if (wd->sc_params.atap_cmd_set1 & WDC_CMD1_CACHE) { bzero(&wdc_c, sizeof(struct wdc_command)); wdc_c.r_command = SET_FEATURES; wdc_c.r_precomp = WDSF_EN_WR_CACHE; wdc_c.timeout = 1000; wdc_c.flags = at_poll; if (wdc_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) { printf("%s: enable write cache command didn't " "complete\n", wd->sc_dev.dv_xname); } } /* * FREEZE LOCK the drive so malicous users can't lock it on us. * As there is no harm in issuing this to drives that don't * support the security feature set we just send it, and don't * bother checking if the drive sends a command abort to tell us it * doesn't support it. */ bzero(&wdc_c, sizeof(struct wdc_command)); wdc_c.r_command = WDCC_SEC_FREEZE_LOCK; wdc_c.timeout = 1000; wdc_c.flags = at_poll; if (wdc_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) { printf("%s: freeze lock command didn't complete\n", wd->sc_dev.dv_xname); } /* * Initialize disk structures. */ wd->sc_dk.dk_name = wd->sc_dev.dv_xname; bufq_init(&wd->sc_bufq, BUFQ_DEFAULT); timeout_set(&wd->sc_restart_timeout, wdrestart, wd); /* Attach disk. */ disk_attach(&wd->sc_dev, &wd->sc_dk); wd->sc_wdc_bio.lp = wd->sc_dk.dk_label; }
/* ARGSUSED */ int vndioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { int unit = DISKUNIT(dev); struct disklabel *lp; struct vnd_softc *sc; struct vnd_ioctl *vio; struct vnd_user *vnu; struct vattr vattr; struct nameidata nd; int error, part, pmask; DNPRINTF(VDB_FOLLOW, "vndioctl(%x, %lx, %p, %x, %p): unit %d\n", dev, cmd, addr, flag, p, unit); error = suser(p, 0); if (error) return (error); if (unit >= numvnd) return (ENXIO); sc = &vnd_softc[unit]; vio = (struct vnd_ioctl *)addr; switch (cmd) { case VNDIOCSET: if (sc->sc_flags & VNF_INITED) return (EBUSY); /* Geometry eventually has to fit into label fields */ if (vio->vnd_secsize > UINT_MAX || vio->vnd_ntracks > UINT_MAX || vio->vnd_nsectors > UINT_MAX) return (EINVAL); if ((error = disk_lock(&sc->sc_dk)) != 0) return (error); if ((error = copyinstr(vio->vnd_file, sc->sc_file, sizeof(sc->sc_file), NULL))) { disk_unlock(&sc->sc_dk); return (error); } /* Set geometry for device. */ sc->sc_secsize = vio->vnd_secsize; sc->sc_ntracks = vio->vnd_ntracks; sc->sc_nsectors = vio->vnd_nsectors; /* * Open for read and write first. This lets vn_open() weed out * directories, sockets, etc. so we don't have to worry about * them. */ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, vio->vnd_file, p); sc->sc_flags &= ~VNF_READONLY; error = vn_open(&nd, FREAD|FWRITE, 0); if (error == EROFS) { sc->sc_flags |= VNF_READONLY; error = vn_open(&nd, FREAD, 0); } if (error) { disk_unlock(&sc->sc_dk); return (error); } if (nd.ni_vp->v_type == VBLK) sc->sc_size = vndbdevsize(nd.ni_vp, p); else { error = VOP_GETATTR(nd.ni_vp, &vattr, p->p_ucred, p); if (error) { VOP_UNLOCK(nd.ni_vp, 0, p); vn_close(nd.ni_vp, VNDRW(sc), p->p_ucred, p); disk_unlock(&sc->sc_dk); return (error); } sc->sc_size = vattr.va_size / sc->sc_secsize; } VOP_UNLOCK(nd.ni_vp, 0, p); sc->sc_vp = nd.ni_vp; if ((error = vndsetcred(sc, p->p_ucred)) != 0) { (void) vn_close(nd.ni_vp, VNDRW(sc), p->p_ucred, p); disk_unlock(&sc->sc_dk); return (error); } if (vio->vnd_keylen > 0) { char key[BLF_MAXUTILIZED]; if (vio->vnd_keylen > sizeof(key)) vio->vnd_keylen = sizeof(key); if ((error = copyin(vio->vnd_key, key, vio->vnd_keylen)) != 0) { (void) vn_close(nd.ni_vp, VNDRW(sc), p->p_ucred, p); disk_unlock(&sc->sc_dk); return (error); } sc->sc_keyctx = malloc(sizeof(*sc->sc_keyctx), M_DEVBUF, M_WAITOK); blf_key(sc->sc_keyctx, key, vio->vnd_keylen); explicit_bzero(key, vio->vnd_keylen); } else sc->sc_keyctx = NULL; vio->vnd_size = sc->sc_size * sc->sc_secsize; sc->sc_flags |= VNF_INITED; DNPRINTF(VDB_INIT, "vndioctl: SET vp %p size %llx\n", sc->sc_vp, (unsigned long long)sc->sc_size); /* Attach the disk. */ sc->sc_dk.dk_name = sc->sc_dev.dv_xname; disk_attach(&sc->sc_dev, &sc->sc_dk); disk_unlock(&sc->sc_dk); break; case VNDIOCCLR: if ((sc->sc_flags & VNF_INITED) == 0) return (ENXIO); if ((error = disk_lock(&sc->sc_dk)) != 0) return (error); /* * Don't unconfigure if any other partitions are open * or if both the character and block flavors of this * partition are open. */ part = DISKPART(dev); pmask = (1 << part); if ((sc->sc_dk.dk_openmask & ~pmask) || ((sc->sc_dk.dk_bopenmask & pmask) && (sc->sc_dk.dk_copenmask & pmask))) { disk_unlock(&sc->sc_dk); return (EBUSY); } vndclear(sc); DNPRINTF(VDB_INIT, "vndioctl: CLRed\n"); /* Free crypto key */ if (sc->sc_keyctx) { explicit_bzero(sc->sc_keyctx, sizeof(*sc->sc_keyctx)); free(sc->sc_keyctx, M_DEVBUF, sizeof(*sc->sc_keyctx)); } /* Detach the disk. */ disk_detach(&sc->sc_dk); disk_unlock(&sc->sc_dk); break; case VNDIOCGET: vnu = (struct vnd_user *)addr; if (vnu->vnu_unit == -1) vnu->vnu_unit = unit; if (vnu->vnu_unit >= numvnd) return (ENXIO); if (vnu->vnu_unit < 0) return (EINVAL); sc = &vnd_softc[vnu->vnu_unit]; if (sc->sc_flags & VNF_INITED) { error = VOP_GETATTR(sc->sc_vp, &vattr, p->p_ucred, p); if (error) return (error); strlcpy(vnu->vnu_file, sc->sc_file, sizeof(vnu->vnu_file)); vnu->vnu_dev = vattr.va_fsid; vnu->vnu_ino = vattr.va_fileid; } else { vnu->vnu_dev = 0; vnu->vnu_ino = 0; } break; case DIOCRLDINFO: if ((sc->sc_flags & VNF_HAVELABEL) == 0) return (ENOTTY); lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK); vndgetdisklabel(dev, sc, lp, 0); *(sc->sc_dk.dk_label) = *lp; free(lp, M_TEMP, sizeof(*lp)); return (0); case DIOCGPDINFO: if ((sc->sc_flags & VNF_HAVELABEL) == 0) return (ENOTTY); vndgetdisklabel(dev, sc, (struct disklabel *)addr, 1); return (0); case DIOCGDINFO: if ((sc->sc_flags & VNF_HAVELABEL) == 0) return (ENOTTY); *(struct disklabel *)addr = *(sc->sc_dk.dk_label); return (0); case DIOCGPART: if ((sc->sc_flags & VNF_HAVELABEL) == 0) return (ENOTTY); ((struct partinfo *)addr)->disklab = sc->sc_dk.dk_label; ((struct partinfo *)addr)->part = &sc->sc_dk.dk_label->d_partitions[DISKPART(dev)]; return (0); case DIOCWDINFO: case DIOCSDINFO: if ((sc->sc_flags & VNF_HAVELABEL) == 0) return (ENOTTY); if ((flag & FWRITE) == 0) return (EBADF); if ((error = disk_lock(&sc->sc_dk)) != 0) return (error); error = setdisklabel(sc->sc_dk.dk_label, (struct disklabel *)addr, /* sc->sc_dk.dk_openmask */ 0); if (error == 0) { if (cmd == DIOCWDINFO) error = writedisklabel(DISKLABELDEV(dev), vndstrategy, sc->sc_dk.dk_label); } disk_unlock(&sc->sc_dk); return (error); default: return (ENOTTY); } return (0); }
/* ARGSUSED */ static int cgd_ioctl_set(struct cgd_softc *cs, void *data, struct lwp *l) { struct cgd_ioctl *ci = data; struct vnode *vp; int ret; size_t i; size_t keybytes; /* key length in bytes */ const char *cp; struct pathbuf *pb; char *inbuf; struct dk_softc *dksc = &cs->sc_dksc; cp = ci->ci_disk; ret = pathbuf_copyin(ci->ci_disk, &pb); if (ret != 0) { return ret; } ret = dk_lookup(pb, l, &vp); pathbuf_destroy(pb); if (ret != 0) { return ret; } inbuf = malloc(MAX_KEYSIZE, M_TEMP, M_WAITOK); if ((ret = cgdinit(cs, cp, vp, l)) != 0) goto bail; (void)memset(inbuf, 0, MAX_KEYSIZE); ret = copyinstr(ci->ci_alg, inbuf, 256, NULL); if (ret) goto bail; cs->sc_cfuncs = cryptfuncs_find(inbuf); if (!cs->sc_cfuncs) { ret = EINVAL; goto bail; } (void)memset(inbuf, 0, MAX_KEYSIZE); ret = copyinstr(ci->ci_ivmethod, inbuf, MAX_KEYSIZE, NULL); if (ret) goto bail; for (i = 0; i < __arraycount(encblkno); i++) if (strcmp(encblkno[i].n, inbuf) == 0) break; if (i == __arraycount(encblkno)) { ret = EINVAL; goto bail; } keybytes = ci->ci_keylen / 8 + 1; if (keybytes > MAX_KEYSIZE) { ret = EINVAL; goto bail; } (void)memset(inbuf, 0, MAX_KEYSIZE); ret = copyin(ci->ci_key, inbuf, keybytes); if (ret) goto bail; cs->sc_cdata.cf_blocksize = ci->ci_blocksize; cs->sc_cdata.cf_mode = encblkno[i].v; cs->sc_cdata.cf_keylen = ci->ci_keylen; cs->sc_cdata.cf_priv = cs->sc_cfuncs->cf_init(ci->ci_keylen, inbuf, &cs->sc_cdata.cf_blocksize); if (cs->sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE) { log(LOG_WARNING, "cgd: Disallowed cipher with blocksize %zu > %u\n", cs->sc_cdata.cf_blocksize, CGD_MAXBLOCKSIZE); cs->sc_cdata.cf_priv = NULL; } /* * The blocksize is supposed to be in bytes. Unfortunately originally * it was expressed in bits. For compatibility we maintain encblkno * and encblkno8. */ cs->sc_cdata.cf_blocksize /= encblkno[i].d; (void)explicit_memset(inbuf, 0, MAX_KEYSIZE); if (!cs->sc_cdata.cf_priv) { ret = EINVAL; /* XXX is this the right error? */ goto bail; } free(inbuf, M_TEMP); bufq_alloc(&dksc->sc_bufq, "fcfs", 0); cs->sc_data = malloc(MAXPHYS, M_DEVBUF, M_WAITOK); cs->sc_data_used = 0; /* Attach the disk. */ dk_attach(dksc); disk_attach(&dksc->sc_dkdev); disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, NULL); /* Discover wedges on this disk. */ dkwedge_discover(&dksc->sc_dkdev); return 0; bail: free(inbuf, M_TEMP); (void)vn_close(vp, FREAD|FWRITE, l->l_cred); return ret; }
void presto_attach(struct device *parent, struct device *self, void *args) { struct presto_softc *sc = (struct presto_softc *)self; struct confargs *ca = args; char *model, *submodel; u_int8_t status; /* Get card parameters */ model = getpropstring(ca->ca_ra.ra_node, "model"); if (*model == '\0') submodel = "fictitious"; else { submodel = memchr(model, ',', strlen(model)); if (submodel != NULL) submodel++; else submodel = model; } strncpy(sc->sc_model, submodel, 16); sc->sc_memsize = ca->ca_ra.ra_len; printf(": %s\n%s: %d MB NVRAM, ", model, sc->sc_dev.dv_xname, sc->sc_memsize >> 20); /* Map memory */ sc->sc_mem = (void *)mapiodev(ca->ca_ra.ra_reg, 0, sc->sc_memsize); /* * Clear the ``disconnect battery'' bit. */ *(u_int8_t *)(sc->sc_mem + PSERVE_BATTERYSTATUS) = 0x00; /* * Clear the ``unflushed data'' status. This way, if the card is * reused under SunOS, the system will not try to flush whatever * data the user put in the nvram... */ *(u_int8_t *)(sc->sc_mem + PSERVE_DATASTATUS) = 0x00; /* * Decode battery status */ status = *(u_int8_t *)(sc->sc_mem + PSERVE_BATTERYSTATUS); printf("battery status %x ", status); if (ISSET(status, PSBAT_FAULT)) { printf("(non-working)"); } else if (ISSET(status, PSBAT_CONNECTED)) { if (ISSET(status, PSBAT_CHARGING)) printf("(charging)"); else printf("(ok)"); } else printf("(disabled)"); printf("\n"); #ifdef DEBUG printf("%s: status codes %02.2x, %02.2x, %02.2x, %02.2x\n", sc->sc_dev.dv_xname, *(u_int8_t *)(sc->sc_mem + 0x03), *(u_int8_t *)(sc->sc_mem + 0x07), *(u_int8_t *)(sc->sc_mem + 0x0b), *(u_int8_t *)(sc->sc_mem + 0x0f)); #endif sc->sc_dk.dk_driver = &presto_dk; sc->sc_dk.dk_name = sc->sc_dev.dv_xname; disk_attach(&sc->sc_dk); /* read the disk label immediately */ presto_getdisklabel(sc); }
int ccdioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { int unit = ccdunit(dev); int i, j, lookedup = 0, error = 0; int part, pmask, s; struct ccd_softc *cs; struct ccd_ioctl *ccio = (struct ccd_ioctl *)data; struct ccddevice ccd; char **cpp; struct vnode **vpp; vaddr_t min, max; if (unit >= numccd) return (ENXIO); cs = &ccd_softc[unit]; if (cmd != CCDIOCSET && !(cs->sc_flags & CCDF_INITED)) return (ENXIO); /* access control */ switch (cmd) { case CCDIOCSET: case CCDIOCCLR: case DIOCWDINFO: case DIOCSDINFO: case DIOCWLABEL: if ((flag & FWRITE) == 0) return (EBADF); } bzero(&ccd, sizeof(ccd)); switch (cmd) { case CCDIOCSET: if (cs->sc_flags & CCDF_INITED) return (EBUSY); if (ccio->ccio_ndisks == 0 || ccio->ccio_ndisks > INT_MAX || ccio->ccio_ileave < 0) return (EINVAL); if ((error = ccdlock(cs)) != 0) return (error); /* Fill in some important bits. */ ccd.ccd_unit = unit; ccd.ccd_interleave = ccio->ccio_ileave; ccd.ccd_flags = ccio->ccio_flags & CCDF_USERMASK; /* XXX the new code is unstable still */ ccd.ccd_flags |= CCDF_OLD; /* * Interleaving which is not a multiple of the click size * must use the old I/O code (by design) */ if (ccio->ccio_ileave % (PAGE_SIZE / DEV_BSIZE) != 0) ccd.ccd_flags |= CCDF_OLD; /* * Allocate space for and copy in the array of * componet pathnames and device numbers. */ cpp = malloc(ccio->ccio_ndisks * sizeof(char *), M_DEVBUF, M_WAITOK); vpp = malloc(ccio->ccio_ndisks * sizeof(struct vnode *), M_DEVBUF, M_WAITOK); error = copyin((caddr_t)ccio->ccio_disks, (caddr_t)cpp, ccio->ccio_ndisks * sizeof(char **)); if (error) { free(vpp, M_DEVBUF); free(cpp, M_DEVBUF); ccdunlock(cs); return (error); } for (i = 0; i < ccio->ccio_ndisks; ++i) { CCD_DPRINTF(CCDB_INIT, ("ccdioctl: component %d: %p, lookedup = %d\n", i, cpp[i], lookedup)); if ((error = ccdlookup(cpp[i], p, &vpp[i])) != 0) { for (j = 0; j < lookedup; ++j) (void)vn_close(vpp[j], FREAD|FWRITE, p->p_ucred, p); free(vpp, M_DEVBUF); free(cpp, M_DEVBUF); ccdunlock(cs); return (error); } ++lookedup; } ccd.ccd_cpp = cpp; ccd.ccd_vpp = vpp; ccd.ccd_ndev = ccio->ccio_ndisks; /* * Initialize the ccd. Fills in the softc for us. */ if ((error = ccdinit(&ccd, cpp, p)) != 0) { for (j = 0; j < lookedup; ++j) (void)vn_close(vpp[j], FREAD|FWRITE, p->p_ucred, p); bzero(&ccd_softc[unit], sizeof(struct ccd_softc)); free(vpp, M_DEVBUF); free(cpp, M_DEVBUF); ccdunlock(cs); return (error); } /* * The ccd has been successfully initialized, so * we can place it into the array. Don't try to * read the disklabel until the disk has been attached, * because space for the disklabel is allocated * in disk_attach(); */ bcopy(&ccd, &ccddevs[unit], sizeof(ccd)); ccio->ccio_unit = unit; ccio->ccio_size = cs->sc_size; /* * If we use the optimized protocol we need some kvm space * for the component buffers. Allocate it here. * * XXX I'd like to have a more dynamic way of acquiring kvm * XXX space, but that is problematic as we are not allowed * XXX to lock the kernel_map in interrupt context. It is * XXX doable via a freelist implementation though. */ if (!ccdmap && !(ccd.ccd_flags & CCDF_OLD)) { min = vm_map_min(kernel_map); ccdmap = uvm_km_suballoc(kernel_map, &min, &max, CCD_CLUSTERS * MAXBSIZE, VM_MAP_INTRSAFE, FALSE, NULL); } /* Attach the disk. */ cs->sc_dkdev.dk_name = cs->sc_xname; disk_attach(&cs->sc_dkdev); /* Try and read the disklabel. */ ccdgetdisklabel(dev, cs, cs->sc_dkdev.dk_label, cs->sc_dkdev.dk_cpulabel, 0); ccdunlock(cs); break; case CCDIOCCLR: if ((error = ccdlock(cs)) != 0) return (error); /* * Don't unconfigure if any other partitions are open * or if both the character and block flavors of this * partition are open. */ part = DISKPART(dev); pmask = (1 << part); if ((cs->sc_dkdev.dk_openmask & ~pmask) || ((cs->sc_dkdev.dk_bopenmask & pmask) && (cs->sc_dkdev.dk_copenmask & pmask))) { ccdunlock(cs); return (EBUSY); } /* * Free ccd_softc information and clear entry. */ /* Close the components and free their pathnames. */ for (i = 0; i < cs->sc_nccdisks; ++i) { /* * XXX: this close could potentially fail and * cause Bad Things. Maybe we need to force * the close to happen? */ #ifdef DIAGNOSTIC CCD_DCALL(CCDB_VNODE, vprint("CCDIOCCLR: vnode info", cs->sc_cinfo[i].ci_vp)); #endif (void)vn_close(cs->sc_cinfo[i].ci_vp, FREAD|FWRITE, p->p_ucred, p); free(cs->sc_cinfo[i].ci_path, M_DEVBUF); } /* Free interleave index. */ for (i = 0; cs->sc_itable[i].ii_ndisk; ++i) free(cs->sc_itable[i].ii_index, M_DEVBUF); /* Free component info and interleave table. */ free(cs->sc_cinfo, M_DEVBUF); free(cs->sc_itable, M_DEVBUF); cs->sc_flags &= ~CCDF_INITED; /* * Free ccddevice information and clear entry. */ free(ccddevs[unit].ccd_cpp, M_DEVBUF); free(ccddevs[unit].ccd_vpp, M_DEVBUF); bcopy(&ccd, &ccddevs[unit], sizeof(ccd)); /* Detatch the disk. */ disk_detach(&cs->sc_dkdev); /* This must be atomic. */ s = splhigh(); ccdunlock(cs); bzero(cs, sizeof(struct ccd_softc)); splx(s); break; case DIOCGPDINFO: { struct cpu_disklabel osdep; if ((error = ccdlock(cs)) != 0) return (error); ccdgetdisklabel(dev, cs, (struct disklabel *)data, &osdep, 1); ccdunlock(cs); break; } case DIOCGDINFO: *(struct disklabel *)data = *(cs->sc_dkdev.dk_label); break; case DIOCGPART: ((struct partinfo *)data)->disklab = cs->sc_dkdev.dk_label; ((struct partinfo *)data)->part = &cs->sc_dkdev.dk_label->d_partitions[DISKPART(dev)]; break; case DIOCWDINFO: case DIOCSDINFO: if ((error = ccdlock(cs)) != 0) return (error); cs->sc_flags |= CCDF_LABELLING; error = setdisklabel(cs->sc_dkdev.dk_label, (struct disklabel *)data, 0, cs->sc_dkdev.dk_cpulabel); if (error == 0) { if (cmd == DIOCWDINFO) error = writedisklabel(CCDLABELDEV(dev), ccdstrategy, cs->sc_dkdev.dk_label, cs->sc_dkdev.dk_cpulabel); } cs->sc_flags &= ~CCDF_LABELLING; ccdunlock(cs); if (error) return (error); break; case DIOCWLABEL: if (*(int *)data != 0) cs->sc_flags |= CCDF_WLABEL; else cs->sc_flags &= ~CCDF_WLABEL; break; default: return (ENOTTY); } return (0); }