/* * Fabricate a default disk label, and try to read the correct one. */ static void edgetdisklabel(dev_t dev, struct ed_softc *ed) { struct disklabel *lp = ed->sc_dk.dk_label; const char *errstring; ATADEBUG_PRINT(("edgetdisklabel\n"), DEBUG_FUNCS); memset(ed->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel)); edgetdefaultlabel(ed, lp); errstring = readdisklabel( EDLABELDEV(dev), edmcastrategy, lp, ed->sc_dk.dk_cpulabel); if (errstring) { /* * This probably happened because the drive's default * geometry doesn't match the DOS geometry. We * assume the DOS geometry is now in the label and try * again. XXX This is a kluge. */ #if 0 if (wd->drvp->state > RECAL) wd->drvp->drive_flags |= ATA_DRIVE_RESET; #endif errstring = readdisklabel(EDLABELDEV(dev), edmcastrategy, lp, ed->sc_dk.dk_cpulabel); } if (errstring) { printf("%s: %s\n", device_xname(ed->sc_dev), errstring); return; } }
/* * Read the disklabel. If none is present, use a fictitious one instead. */ void presto_getdisklabel(struct presto_softc *sc) { struct disklabel *lp = sc->sc_dk.dk_label; bzero(sc->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel)); bzero(sc->sc_dk.dk_label, sizeof(struct disklabel)); lp->d_secsize = DEV_BSIZE; lp->d_ntracks = 1; lp->d_nsectors = 32; lp->d_secperunit = (sc->sc_memsize - PSERVE_OFFSET) >> DEV_BSHIFT; lp->d_ncylinders = lp->d_secperunit / lp->d_nsectors; lp->d_secpercyl = lp->d_nsectors; strncpy(lp->d_typename, "Prestoserve", 16); lp->d_type = DTYPE_SCSI; /* what better to put here? */ strncpy(lp->d_packname, sc->sc_model, 16); lp->d_rpm = 3600; lp->d_interleave = 1; lp->d_partitions[RAW_PART].p_offset = 0; lp->d_partitions[RAW_PART].p_size = lp->d_secperunit; lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; lp->d_npartitions = RAW_PART + 1; lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; lp->d_checksum = dkcksum(lp); readdisklabel(DISKLABELDEV(sc->sc_dev.dv_unit), prestostrategy, sc->sc_dk.dk_label, sc->sc_dk.dk_cpulabel, 0); }
int rdgetdisklabel(dev_t dev, struct rd_softc *sc, struct disklabel *lp, int spoofonly) { bzero(lp, sizeof(struct disklabel)); lp->d_secsize = DEV_BSIZE; lp->d_ntracks = 1; lp->d_nsectors = rd_root_size >> DEV_BSHIFT; lp->d_ncylinders = 1; lp->d_secpercyl = lp->d_nsectors; if (lp->d_secpercyl == 0) { lp->d_secpercyl = 100; /* as long as it's not 0 - readdisklabel divides by it */ } strncpy(lp->d_typename, "RAM disk", sizeof(lp->d_typename)); lp->d_type = DTYPE_SCSI; strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname)); DL_SETDSIZE(lp, lp->d_nsectors); lp->d_version = 1; lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; lp->d_checksum = dkcksum(lp); /* Call the generic disklabel extraction routine. */ return (readdisklabel(DISKLABELDEV(dev), rdstrategy, lp, spoofonly)); }
int fdgetdisklabel(dev_t dev, struct fd_softc *fd, struct disklabel *lp, int spoofonly) { bzero(lp, sizeof(struct disklabel)); lp->d_type = DTYPE_FLOPPY; lp->d_secsize = FD_BSIZE(fd); lp->d_secpercyl = fd->sc_type->seccyl; lp->d_nsectors = fd->sc_type->sectrac; lp->d_ncylinders = fd->sc_type->tracks; lp->d_ntracks = fd->sc_type->heads; /* Go figure... */ DL_SETDSIZE(lp, fd->sc_type->size); strncpy(lp->d_typename, "floppy disk", sizeof(lp->d_typename)); strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname)); lp->d_version = 1; lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; lp->d_checksum = dkcksum(lp); /* * Call the generic disklabel extraction routine. If there's * not a label there, fake it. */ return readdisklabel(DISKLABELDEV(dev), fdstrategy, lp, spoofonly); }
/* * (Try to) put the drive online. This is done the first time the * drive is opened, or if it has fallen offline. */ int ra_putonline(dev_t dev, struct ra_softc *ra) { struct disklabel *dl; const char *msg; if (rx_putonline(ra) != MSCP_DONE) return MSCP_FAILED; dl = ra->ra_disk.dk_label; ra->ra_state = DK_RDLABEL; printf("%s", device_xname(ra->ra_dev)); if ((msg = readdisklabel( MAKEDISKDEV(major(dev), device_unit(ra->ra_dev), RAW_PART), rastrategy, dl, NULL)) == NULL) { ra->ra_havelabel = 1; ra->ra_state = DK_OPEN; } #if NRACD else if (cdevsw_lookup(dev) == &racd_cdevsw) { dl->d_partitions[0].p_offset = 0; dl->d_partitions[0].p_size = dl->d_secperunit; dl->d_partitions[0].p_fstype = FS_ISO9660; } #endif /* NRACD */ else { printf(": %s", msg); } printf(": size %d sectors\n", dl->d_secperunit); return MSCP_DONE; }
/* * Load the label information on the named device */ int vndgetdisklabel(dev_t dev, struct vnd_softc *sc, struct disklabel *lp, int spoofonly) { memset(lp, 0, sizeof(struct disklabel)); lp->d_secsize = sc->sc_secsize; lp->d_nsectors = sc->sc_nsectors; lp->d_ntracks = sc->sc_ntracks; lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; lp->d_ncylinders = sc->sc_size / lp->d_secpercyl; strncpy(lp->d_typename, "vnd device", sizeof(lp->d_typename)); lp->d_type = DTYPE_VND; strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname)); DL_SETDSIZE(lp, sc->sc_size); lp->d_flags = 0; lp->d_version = 1; lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; lp->d_checksum = dkcksum(lp); /* Call the generic disklabel extraction routine */ return readdisklabel(DISKLABELDEV(dev), vndstrategy, lp, spoofonly); }
int rlopen(dev_t dev, int flag, int fmt, struct lwp *l) { struct rl_softc * const rc = device_lookup_private(&rl_cd, DISKUNIT(dev)); struct rlc_softc *sc; int error, part, mask; struct disklabel *dl; const char *msg; /* * Make sure this is a reasonable open request. */ if (rc == NULL) return ENXIO; sc = rc->rc_rlc; part = DISKPART(dev); mutex_enter(&rc->rc_disk.dk_openlock); /* * If there are wedges, and this is not RAW_PART, then we * need to fail. */ if (rc->rc_disk.dk_nwedges != 0 && part != RAW_PART) { error = EBUSY; goto bad1; } /* Check that the disk actually is useable */ msg = rlstate(sc, rc->rc_hwid); if (msg == NULL || msg == rlstates[RLMP_UNLOAD] || msg == rlstates[RLMP_SPUNDOWN]) { error = ENXIO; goto bad1; } /* * If this is the first open; read in where on the disk we are. */ dl = rc->rc_disk.dk_label; if (rc->rc_state == DK_CLOSED) { u_int16_t mp; int maj; RL_WREG(RL_CS, RLCS_RHDR|(rc->rc_hwid << RLCS_USHFT)); waitcrdy(sc); mp = RL_RREG(RL_MP); rc->rc_head = ((mp & RLMP_HS) == RLMP_HS); rc->rc_cyl = (mp >> 7) & 0777; rc->rc_state = DK_OPEN; /* Get disk label */ maj = cdevsw_lookup_major(&rl_cdevsw); if ((msg = readdisklabel(MAKEDISKDEV(maj, device_unit(rc->rc_dev), RAW_PART), rlstrategy, dl, NULL))) aprint_normal_dev(rc->rc_dev, "%s", msg); aprint_normal_dev(rc->rc_dev, "size %d sectors\n", dl->d_secperunit); }
/* * Load the label information from the specified device. */ static void ldgetdisklabel(struct ld_softc *sc) { const char *errstring; ldgetdefaultlabel(sc, sc->sc_dk.dk_label); /* Call the generic disklabel extraction routine. */ errstring = readdisklabel(MAKEDISKDEV(0, sc->sc_dv.dv_unit, RAW_PART), ldstrategy, sc->sc_dk.dk_label, sc->sc_dk.dk_cpulabel); if (errstring != NULL) printf("%s: %s\n", sc->sc_dv.dv_xname, errstring); }
/* * Read the disklabel from a vnd. If one is not present, create a fake one. */ static void vndgetdisklabel(dev_t dev, struct vnd_softc *sc) { const char *errstring; struct disklabel *lp = sc->sc_dkdev.dk_label; struct cpu_disklabel *clp = sc->sc_dkdev.dk_cpulabel; int i; memset(clp, 0, sizeof(*clp)); vndgetdefaultlabel(sc, lp); /* * Call the generic disklabel extraction routine. */ errstring = readdisklabel(VNDLABELDEV(dev), vndstrategy, lp, clp); if (errstring) { /* * Lack of disklabel is common, but we print the warning * anyway, since it might contain other useful information. */ aprint_normal_dev(sc->sc_dev, "%s\n", errstring); /* * For historical reasons, if there's no disklabel * present, all partitions must be FS_BSDFFS and * occupy the entire disk. */ for (i = 0; i < MAXPARTITIONS; i++) { /* * Don't wipe out port specific hack (such as * dos partition hack of i386 port). */ if (lp->d_partitions[i].p_size != 0) continue; lp->d_partitions[i].p_size = lp->d_secperunit; lp->d_partitions[i].p_offset = 0; lp->d_partitions[i].p_fstype = FS_BSDFFS; } strncpy(lp->d_packname, "default label", sizeof(lp->d_packname)); lp->d_npartitions = MAXPARTITIONS; lp->d_checksum = dkcksum(lp); } }
/* * Fabricate a default disk label, and try to read the correct one. */ int wdgetdisklabel(dev_t dev, struct wd_softc *wd, struct disklabel *lp, int spoofonly) { int error; WDCDEBUG_PRINT(("wdgetdisklabel\n"), DEBUG_FUNCS); wdgetdefaultlabel(wd, lp); if (wd->drvp->state > RECAL) wd->drvp->drive_flags |= DRIVE_RESET; error = readdisklabel(DISKLABELDEV(dev), wdstrategy, lp, spoofonly); if (wd->drvp->state > RECAL) wd->drvp->drive_flags |= DRIVE_RESET; return (error); }
/* ARGSUSED */ void dk_getdisklabel(struct dk_softc *dksc, dev_t dev) { const struct dkdriver *dkd = dksc->sc_dkdev.dk_driver; struct disklabel *lp = dksc->sc_dkdev.dk_label; struct cpu_disklabel *clp = dksc->sc_dkdev.dk_cpulabel; struct disk_geom *dg = &dksc->sc_dkdev.dk_geom; struct partition *pp; int i; const char *errstring; memset(clp, 0x0, sizeof(*clp)); dk_getdefaultlabel(dksc, lp); errstring = readdisklabel(DKLABELDEV(dev), dkd->d_strategy, dksc->sc_dkdev.dk_label, dksc->sc_dkdev.dk_cpulabel); if (errstring) { dk_makedisklabel(dksc); if (dksc->sc_flags & DKF_WARNLABEL) printf("%s: %s\n", dksc->sc_xname, errstring); return; } if ((dksc->sc_flags & DKF_LABELSANITY) == 0) return; /* Sanity check */ if (lp->d_secperunit < UINT32_MAX ? lp->d_secperunit != dg->dg_secperunit : lp->d_secperunit > dg->dg_secperunit) printf("WARNING: %s: total sector size in disklabel (%ju) " "!= the size of %s (%ju)\n", dksc->sc_xname, (uintmax_t)lp->d_secperunit, dksc->sc_xname, (uintmax_t)dg->dg_secperunit); for (i=0; i < lp->d_npartitions; i++) { pp = &lp->d_partitions[i]; if (pp->p_offset + pp->p_size > dg->dg_secperunit) printf("WARNING: %s: end of partition `%c' exceeds " "the size of %s (%ju)\n", dksc->sc_xname, 'a' + i, dksc->sc_xname, (uintmax_t)dg->dg_secperunit); } }
/* * Read the disklabel from the ccd. If one is not present, fake one * up. */ void ccdgetdisklabel(dev_t dev, struct ccd_softc *cs, struct disklabel *lp, struct cpu_disklabel *clp, int spoofonly) { struct ccdgeom *ccg = &cs->sc_geom; char *errstring; bzero(lp, sizeof(*lp)); bzero(clp, sizeof(*clp)); lp->d_secperunit = cs->sc_size; lp->d_secsize = ccg->ccg_secsize; lp->d_nsectors = ccg->ccg_nsectors; lp->d_ntracks = ccg->ccg_ntracks; lp->d_ncylinders = ccg->ccg_ncylinders; lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; lp->d_rpm = ccg->ccg_rpm; strncpy(lp->d_typename, "ccd", sizeof(lp->d_typename)); lp->d_type = DTYPE_CCD; strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname)); lp->d_interleave = 1; lp->d_flags = 0; lp->d_partitions[RAW_PART].p_offset = 0; lp->d_partitions[RAW_PART].p_size = lp->d_secperunit; lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; lp->d_npartitions = RAW_PART + 1; lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; lp->d_checksum = dkcksum(cs->sc_dkdev.dk_label); /* * Call the generic disklabel extraction routine. */ errstring = readdisklabel(CCDLABELDEV(dev), ccdstrategy, cs->sc_dkdev.dk_label, cs->sc_dkdev.dk_cpulabel, spoofonly); /* It's actually extremely common to have unlabeled ccds. */ if (errstring != NULL) CCD_DPRINTF(CCDB_LABEL, ("%s: %s\n", cs->sc_xname, errstring)); }
int rlopen(dev_t dev, int flag, int fmt, struct proc *p) { int part, unit, mask; struct disklabel *dl; struct rlc_softc *sc; struct rl_softc *rc; char *msg; /* * Make sure this is a reasonable open request. */ unit = DISKUNIT(dev); if (unit >= rl_cd.cd_ndevs) return ENXIO; rc = rl_cd.cd_devs[unit]; if (rc == 0) return ENXIO; sc = (struct rlc_softc *)rc->rc_dev.dv_parent; /* XXX - check that the disk actually is useable */ /* * If this is the first open; read in where on the disk we are. */ dl = rc->rc_disk.dk_label; if (rc->rc_state == DK_CLOSED) { u_int16_t mp; RL_WREG(RL_CS, RLCS_RHDR|(rc->rc_hwid << RLCS_USHFT)); waitcrdy(sc); mp = RL_RREG(RL_MP); rc->rc_head = ((mp & RLMP_HS) == RLMP_HS); rc->rc_cyl = (mp >> 7) & 0777; rc->rc_state = DK_OPEN; /* Get disk label */ printf("%s: ", rc->rc_dev.dv_xname); if ((msg = readdisklabel(MAKEDISKDEV(RLMAJOR, rc->rc_dev.dv_unit, RAW_PART), rlstrategy, dl, NULL))) printf("%s: ", msg); printf("size %d sectors\n", dl->d_secperunit); }
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 }
void ofdisk_getdisklabel(dev_t dev) { int unit = DISKUNIT(dev); struct ofdisk_softc *of = device_lookup_private(&ofdisk_cd, unit); struct disklabel *lp = of->sc_dk.dk_label; const char *errmes; int l; ofdisk_getdefaultlabel(of, lp); /* * Don't read the disklabel on a floppy; simply * assign all partitions the same size/offset as * RAW_PART. (This is essentially what the ISA * floppy driver does, but we don't deal with * density stuff.) */ if (OFDISK_FLOPPY_P(of)) { lp->d_npartitions = MAXPARTITIONS; for (l = 0; l < lp->d_npartitions; l++) { if (l == RAW_PART) continue; /* struct copy */ lp->d_partitions[l] = lp->d_partitions[RAW_PART]; } lp->d_checksum = dkcksum(lp); } else { errmes = readdisklabel(MAKEDISKDEV(major(dev), unit, RAW_PART), ofdisk_strategy, lp, of->sc_dk.dk_cpulabel); if (errmes != NULL) printf("%s: %s\n", device_xname(of->sc_dev), errmes); } }
/* ARGSUSED */ void dk_getdisklabel(struct dk_intf *di, struct dk_softc *dksc, dev_t dev) { struct disklabel *lp = dksc->sc_dkdev.dk_label; struct cpu_disklabel *clp = dksc->sc_dkdev.dk_cpulabel; struct partition *pp; int i; const char *errstring; memset(clp, 0x0, sizeof(*clp)); dk_getdefaultlabel(di, dksc, lp); errstring = readdisklabel(DKLABELDEV(dev), di->di_strategy, dksc->sc_dkdev.dk_label, dksc->sc_dkdev.dk_cpulabel); if (errstring) { dk_makedisklabel(di, dksc); if (dksc->sc_flags & DKF_WARNLABEL) printf("%s: %s\n", dksc->sc_xname, errstring); return; } if ((dksc->sc_flags & DKF_LABELSANITY) == 0) return; /* Sanity check */ if (lp->d_secperunit != dksc->sc_size) printf("WARNING: %s: total sector size in disklabel (%d) " "!= the size of %s (%lu)\n", dksc->sc_xname, lp->d_secperunit, di->di_dkname, (u_long)dksc->sc_size); for (i=0; i < lp->d_npartitions; i++) { pp = &lp->d_partitions[i]; if (pp->p_offset + pp->p_size > dksc->sc_size) printf("WARNING: %s: end of partition `%c' exceeds " "the size of %s (%lu)\n", dksc->sc_xname, 'a' + i, di->di_dkname, (u_long)dksc->sc_size); } }
/* * Load the label information on the named device * Actually fabricate a disklabel * * EVENTUALLY take information about different * data tracks from the TOC and put it in the disklabel */ void cdgetdisklabel(dev_t dev, struct cd_softc *cd, struct disklabel *lp, int spoofonly) { struct cd_toc *toc; char *errstring; int tocidx, n, audioonly = 1; bzero(lp, sizeof(struct disklabel)); toc = malloc(sizeof(*toc), M_TEMP, M_WAITOK | M_ZERO); lp->d_secsize = cd->params.blksize; lp->d_ntracks = 1; lp->d_nsectors = 100; lp->d_secpercyl = 100; lp->d_ncylinders = (cd->params.disksize / 100) + 1; if (cd->sc_link->flags & SDEV_ATAPI) { strncpy(lp->d_typename, "ATAPI CD-ROM", sizeof(lp->d_typename)); lp->d_type = DTYPE_ATAPI; } else { strncpy(lp->d_typename, "SCSI CD-ROM", sizeof(lp->d_typename)); lp->d_type = DTYPE_SCSI; } strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname)); DL_SETDSIZE(lp, cd->params.disksize); lp->d_rpm = 300; lp->d_interleave = 1; lp->d_version = 1; /* XXX - these values for BBSIZE and SBSIZE assume ffs */ lp->d_bbsize = BBSIZE; lp->d_sbsize = SBSIZE; lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; lp->d_checksum = dkcksum(lp); if (cd_load_toc(cd, toc, CD_LBA_FORMAT)) { audioonly = 0; /* No valid TOC found == not an audio CD. */ goto done; } n = toc->header.ending_track - toc->header.starting_track + 1; for (tocidx = 0; tocidx < n; tocidx++) if (toc->entries[tocidx].control & 4) { audioonly = 0; /* Found a non-audio track. */ goto done; } done: free(toc, M_TEMP); if (!audioonly) { errstring = readdisklabel(DISKLABELDEV(dev), cdstrategy, lp, spoofonly); /*if (errstring) printf("%s: %s\n", cd->sc_dev.dv_xname, errstring);*/ } }
/* * Load the label information on the named device */ int sdgetdisklabel(dev_t dev, struct sd_softc *sc, struct disklabel *lp, int spoofonly) { size_t len; char packname[sizeof(lp->d_packname) + 1]; char product[17], vendor[9]; bzero(lp, sizeof(struct disklabel)); lp->d_secsize = sc->params.secsize; lp->d_ntracks = sc->params.heads; lp->d_nsectors = sc->params.sectors; lp->d_ncylinders = sc->params.cyls; lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; if (lp->d_secpercyl == 0) { lp->d_secpercyl = 100; /* as long as it's not 0 - readdisklabel divides by it */ } lp->d_type = DTYPE_SCSI; if ((sc->sc_link->inqdata.device & SID_TYPE) == T_OPTICAL) strncpy(lp->d_typename, "SCSI optical", sizeof(lp->d_typename)); else strncpy(lp->d_typename, "SCSI disk", sizeof(lp->d_typename)); /* * Try to fit '<vendor> <product>' into d_packname. If that doesn't fit * then leave out '<vendor> ' and use only as much of '<product>' as * does fit. */ viscpy(vendor, sc->sc_link->inqdata.vendor, 8); viscpy(product, sc->sc_link->inqdata.product, 16); len = snprintf(packname, sizeof(packname), "%s %s", vendor, product); if (len > sizeof(lp->d_packname)) { strlcpy(packname, product, sizeof(packname)); len = strlen(packname); } /* * It is safe to use len as the count of characters to copy because * packname is sizeof(lp->d_packname)+1, the string in packname is * always null terminated and len does not count the terminating null. * d_packname is not a null terminated string. */ bcopy(packname, lp->d_packname, len); DL_SETDSIZE(lp, sc->params.disksize); lp->d_version = 1; lp->d_flags = 0; /* XXX - these values for BBSIZE and SBSIZE assume ffs */ lp->d_bbsize = BBSIZE; lp->d_sbsize = SBSIZE; lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; lp->d_checksum = dkcksum(lp); /* * Call the generic disklabel extraction routine */ return readdisklabel(DISKLABELDEV(dev), sdstrategy, lp, spoofonly); }
int fdioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) { struct fd_softc *fd = device_lookup_private(&fd_cd, FDUNIT(dev)); struct fdformat_parms *form_parms; struct fdformat_cmd *form_cmd; struct ne7_fd_formb *fd_formb; struct disklabel buffer; int error; unsigned int scratch; int il[FD_MAX_NSEC + 1]; int i, j; #ifdef __HAVE_OLD_DISKLABEL struct disklabel newlabel; #endif switch (cmd) { case DIOCGDINFO: #ifdef __HAVE_OLD_DISKLABEL case ODIOCGDINFO: #endif memset(&buffer, 0, sizeof(buffer)); buffer.d_secpercyl = fd->sc_type->seccyl; buffer.d_type = DTYPE_FLOPPY; buffer.d_secsize = FDC_BSIZE; if (readdisklabel(dev, fdstrategy, &buffer, NULL) != NULL) return EINVAL; #ifdef __HAVE_OLD_DISKLABEL if (cmd == ODIOCGDINFO) { if (buffer.d_npartitions > OLDMAXPARTITIONS) return ENOTTY; memcpy(addr, &buffer, sizeof (struct olddisklabel)); } else #endif *(struct disklabel *)addr = buffer; return 0; case DIOCWLABEL: if ((flag & FWRITE) == 0) return EBADF; /* XXX do something */ return 0; case DIOCWDINFO: #ifdef __HAVE_OLD_DISKLABEL case ODIOCWDINFO: #endif { struct disklabel *lp; if ((flag & FWRITE) == 0) return EBADF; #ifdef __HAVE_OLD_DISKLABEL if (cmd == ODIOCWDINFO) { memset(&newlabel, 0, sizeof newlabel); memcpy(&newlabel, addr, sizeof (struct olddisklabel)); lp = &newlabel; } else #endif lp = (struct disklabel *)addr; error = setdisklabel(&buffer, lp, 0, NULL); if (error) return error; error = writedisklabel(dev, fdstrategy, &buffer, NULL); return error; } case FDIOCGETFORMAT: form_parms = (struct fdformat_parms *)addr; form_parms->fdformat_version = FDFORMAT_VERSION; form_parms->nbps = 128 * (1 << fd->sc_type->secsize); form_parms->ncyl = fd->sc_type->cyls; form_parms->nspt = fd->sc_type->sectrac; form_parms->ntrk = fd->sc_type->heads; form_parms->stepspercyl = fd->sc_type->step; form_parms->gaplen = fd->sc_type->gap2; form_parms->fillbyte = fd->sc_type->fillbyte; form_parms->interleave = fd->sc_type->interleave; switch (fd->sc_type->rate) { case FDC_500KBPS: form_parms->xfer_rate = 500 * 1024; break; case FDC_300KBPS: form_parms->xfer_rate = 300 * 1024; break; case FDC_250KBPS: form_parms->xfer_rate = 250 * 1024; break; default: return EINVAL; } return 0; case FDIOCSETFORMAT: if((flag & FWRITE) == 0) return EBADF; /* must be opened for writing */ form_parms = (struct fdformat_parms *)addr; if (form_parms->fdformat_version != FDFORMAT_VERSION) return EINVAL; /* wrong version of formatting prog */ scratch = form_parms->nbps >> 7; if ((form_parms->nbps & 0x7f) || ffs(scratch) == 0 || scratch & ~(1 << (ffs(scratch)-1))) /* not a power-of-two multiple of 128 */ return EINVAL; switch (form_parms->xfer_rate) { case 500 * 1024: fd->sc_type->rate = FDC_500KBPS; break; case 300 * 1024: fd->sc_type->rate = FDC_300KBPS; break; case 250 * 1024: fd->sc_type->rate = FDC_250KBPS; break; default: return EINVAL; } if (form_parms->nspt > FD_MAX_NSEC || form_parms->fillbyte > 0xff || form_parms->interleave > 0xff) return EINVAL; fd->sc_type->sectrac = form_parms->nspt; if (form_parms->ntrk != 2 && form_parms->ntrk != 1) return EINVAL; fd->sc_type->heads = form_parms->ntrk; fd->sc_type->seccyl = form_parms->nspt * form_parms->ntrk; fd->sc_type->secsize = ffs(scratch)-1; fd->sc_type->gap2 = form_parms->gaplen; fd->sc_type->cyls = form_parms->ncyl; fd->sc_type->size = fd->sc_type->seccyl * form_parms->ncyl * form_parms->nbps / DEV_BSIZE; fd->sc_type->step = form_parms->stepspercyl; fd->sc_type->fillbyte = form_parms->fillbyte; fd->sc_type->interleave = form_parms->interleave; return 0; case FDIOCFORMAT_TRACK: if((flag & FWRITE) == 0) return EBADF; /* must be opened for writing */ form_cmd = (struct fdformat_cmd *)addr; if (form_cmd->formatcmd_version != FDFORMAT_VERSION) return EINVAL; /* wrong version of formatting prog */ if (form_cmd->head >= fd->sc_type->heads || form_cmd->cylinder >= fd->sc_type->cyls) { return EINVAL; } fd_formb = malloc(sizeof(struct ne7_fd_formb), M_TEMP, M_NOWAIT); if (fd_formb == 0) return ENOMEM; fd_formb->head = form_cmd->head; fd_formb->cyl = form_cmd->cylinder; fd_formb->transfer_rate = fd->sc_type->rate; fd_formb->fd_formb_secshift = fd->sc_type->secsize; fd_formb->fd_formb_nsecs = fd->sc_type->sectrac; fd_formb->fd_formb_gaplen = fd->sc_type->gap2; fd_formb->fd_formb_fillbyte = fd->sc_type->fillbyte; memset(il, 0, sizeof il); for (j = 0, i = 1; i <= fd_formb->fd_formb_nsecs; i++) { while (il[(j%fd_formb->fd_formb_nsecs)+1]) j++; il[(j%fd_formb->fd_formb_nsecs)+1] = i; j += fd->sc_type->interleave; } for (i = 0; i < fd_formb->fd_formb_nsecs; i++) { fd_formb->fd_formb_cylno(i) = form_cmd->cylinder; fd_formb->fd_formb_headno(i) = form_cmd->head; fd_formb->fd_formb_secno(i) = il[i+1]; fd_formb->fd_formb_secsize(i) = fd->sc_type->secsize; } error = fdformat(dev, fd_formb, l); free(fd_formb, M_TEMP); return error; case FDIOCGETOPTS: /* get drive options */ *(int *)addr = fd->sc_opts; return 0; case FDIOCSETOPTS: /* set drive options */ fd->sc_opts = *(int *)addr; return 0; default: return ENOTTY; } #ifdef DIAGNOSTIC panic("fdioctl: impossible"); #endif }