#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: disksubr.c,v 1.36 2019/04/03 22:10:50 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/device.h>
#define FSTYPENAMES
#include <sys/disklabel.h>
#include <sys/disk.h>
#include <dev/scsipi/scsi_all.h>
#include <dev/scsipi/scsipi_all.h>
#include <dev/scsipi/scsiconf.h>
#include <machine/autoconf.h>
#ifdef DEBUG
int disksubr_debug = 0;
#endif
static void bsdtocpulabel(struct disklabel *lp, struct cpu_disklabel *clp);
static void cputobsdlabel(struct disklabel *lp, struct cpu_disklabel *clp);
#ifdef DEBUG
static void printlp(struct disklabel *lp, const char *str);
static void printclp(struct cpu_disklabel *clp, const char *str);
#endif
const char *
readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp,
struct cpu_disklabel *clp)
{
struct buf *bp;
const char *msg = NULL;
bp = geteblk((int)lp->d_secsize);
bp->b_dev = dev;
bp->b_blkno = 0;
bp->b_bcount = lp->d_secsize;
bp->b_flags |= B_READ;
bp->b_cylinder = 0;
(*strat)(bp);
if (biowait(bp)) {
msg = "cpu_disklabel read error\n";
} else {
memcpy(clp, bp->b_data, sizeof (struct cpu_disklabel));
}
brelse(bp, 0);
if (msg || clp->magic1 != DISKMAGIC || clp->magic2 != DISKMAGIC) {
return msg;
}
cputobsdlabel(lp, clp);
#ifdef DEBUG
if(disksubr_debug > 0) {
printlp(lp, "readdisklabel: bsd label");
printclp(clp, "readdisklabel: cpu label");
}
#endif
return msg;
}
int
writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp,
struct cpu_disklabel *clp)
{
struct buf *bp;
int error;
#ifdef DEBUG
if(disksubr_debug > 0) {
printlp(lp, "writedisklabel: bsd label");
}
#endif
bp = geteblk((int)lp->d_secsize);
bp->b_dev = dev;
bp->b_blkno = 0;
bp->b_bcount = lp->d_secsize;
bp->b_flags |= B_READ;
bp->b_cylinder = 0;
(*strat)(bp);
if ( (error = biowait(bp)) != 0 ) {
} else {
memcpy(clp, bp->b_data, sizeof(struct cpu_disklabel));
}
brelse(bp, 0);
if (error) {
return error;
}
bsdtocpulabel(lp, clp);
#ifdef DEBUG
if (disksubr_debug > 0) {
printclp(clp, "writedisklabel: cpu label");
}
#endif
if (lp->d_magic == DISKMAGIC && lp->d_magic2 == DISKMAGIC &&
dkcksum(lp) == 0) {
bp = geteblk((int)lp->d_secsize);
memcpy(bp->b_data, clp, sizeof(struct cpu_disklabel));
bp->b_dev = dev;
bp->b_blkno = 0;
bp->b_bcount = lp->d_secsize;
bp->b_flags |= B_WRITE;
bp->b_cylinder = 0;
(*strat)(bp);
error = biowait(bp);
brelse(bp, 0);
}
return error;
}
static void
bsdtocpulabel(struct disklabel *lp, struct cpu_disklabel *clp)
{
int i;
clp->magic1 = lp->d_magic;
clp->type = lp->d_type;
clp->subtype = lp->d_subtype;
strncpy(clp->vid_vd, lp->d_typename, 16);
strncpy(clp->packname, lp->d_packname, 16);
clp->cfg_psm = lp->d_secsize;
clp->cfg_spt = lp->d_nsectors;
clp->cfg_trk = lp->d_ncylinders;
clp->cfg_hds = lp->d_ntracks;
clp->secpercyl = lp->d_secpercyl;
clp->secperunit = lp->d_secperunit;
clp->sparespertrack = lp->d_sparespertrack;
clp->sparespercyl = lp->d_sparespercyl;
clp->acylinders = lp->d_acylinders;
clp->rpm = lp->d_rpm;
clp->cfg_ilv = lp->d_interleave;
clp->cfg_sof = lp->d_trackskew;
clp->cylskew = lp->d_cylskew;
clp->headswitch = lp->d_headswitch;
if (lp->d_trkseek < 6) {
clp->cfg_ssr = 0;
} else if (lp->d_trkseek < 10) {
clp->cfg_ssr = 1;
} else if (lp->d_trkseek < 15) {
clp->cfg_ssr = 2;
} else if (lp->d_trkseek < 20) {
clp->cfg_ssr = 3;
} else {
clp->cfg_ssr = 4;
}
clp->flags = lp->d_flags;
for (i = 0; i < NDDATA; i++)
clp->drivedata[i] = lp->d_drivedata[i];
for (i = 0; i < NSPARE; i++)
clp->spare[i] = lp->d_spare[i];
clp->magic2 = lp->d_magic2;
clp->checksum = lp->d_checksum;
clp->partitions = lp->d_npartitions;
clp->bbsize = lp->d_bbsize;
clp->sbsize = lp->d_sbsize;
clp->checksum = lp->d_checksum;
memcpy(clp->vid_4, &lp->d_partitions[0], sizeof(struct partition) * 4);
memset(clp->cfg_4, 0, sizeof(struct partition) * 12);
memcpy(clp->cfg_4, &lp->d_partitions[4], sizeof(struct partition)
* ((MAXPARTITIONS < 16) ? (MAXPARTITIONS - 4) : 12));
memcpy(clp->vid_id, VID_ID, sizeof(clp->vid_id));
clp->vid_oss = VID_OSS;
clp->vid_osl = VID_OSL;
clp->vid_osa_u = VID_OSAU;
clp->vid_osa_l = VID_OSAL;
clp->vid_cas = VID_CAS;
clp->vid_cal = VID_CAL;
memcpy(clp->vid_mot, VID_MOT, sizeof(clp->vid_mot));
clp->cfg_rec = CFG_REC;
clp->cfg_psm = CFG_PSM;
}
static void
cputobsdlabel(struct disklabel *lp, struct cpu_disklabel *clp)
{
int i;
lp->d_magic = clp->magic1;
lp->d_type = clp->type;
lp->d_subtype = clp->subtype;
strncpy(lp->d_typename, clp->vid_vd, 16);
strncpy(lp->d_packname, clp->packname, 16);
lp->d_secsize = clp->cfg_psm;
lp->d_nsectors = clp->cfg_spt;
lp->d_ncylinders = clp->cfg_trk;
lp->d_ntracks = clp->cfg_hds;
lp->d_secpercyl = clp->secpercyl;
lp->d_secperunit = clp->secperunit;
lp->d_secpercyl = clp->secpercyl;
lp->d_secperunit = clp->secperunit;
lp->d_sparespertrack = clp->sparespertrack;
lp->d_sparespercyl = clp->sparespercyl;
lp->d_acylinders = clp->acylinders;
lp->d_rpm = clp->rpm;
lp->d_interleave = clp->cfg_ilv;
lp->d_trackskew = clp->cfg_sof;
lp->d_cylskew = clp->cylskew;
lp->d_headswitch = clp->headswitch;
switch (clp->cfg_ssr) {
case 0:
lp->d_trkseek = 0;
break;
case 1:
lp->d_trkseek = 6;
break;
case 2:
lp->d_trkseek = 10;
break;
case 3:
lp->d_trkseek = 15;
break;
case 4:
lp->d_trkseek = 20;
break;
default:
lp->d_trkseek = 0;
}
lp->d_flags = clp->flags;
for (i = 0; i < NDDATA; i++)
lp->d_drivedata[i] = clp->drivedata[i];
for (i = 0; i < NSPARE; i++)
lp->d_spare[i] = clp->spare[i];
lp->d_magic2 = clp->magic2;
lp->d_checksum = clp->checksum;
lp->d_npartitions = clp->partitions;
lp->d_bbsize = clp->bbsize;
lp->d_sbsize = clp->sbsize;
memcpy(&lp->d_partitions[0], clp->vid_4, sizeof(struct partition) * 4);
memcpy(&lp->d_partitions[4], clp->cfg_4, sizeof(struct partition)
* ((MAXPARTITIONS < 16) ? (MAXPARTITIONS - 4) : 12));
lp->d_checksum = 0;
lp->d_checksum = dkcksum(lp);
#if DEBUG
if (disksubr_debug > 0) {
printlp(lp, "translated label read from disk\n");
}
#endif
}
#ifdef DEBUG
static void
printlp(struct disklabel *lp, const char *str)
{
int i;
printf("%s\n", str);
printf("magic1 %x\n", lp->d_magic);
printf("magic2 %x\n", lp->d_magic2);
printf("typename %s\n", lp->d_typename);
printf("secsize %x nsect %x ntrack %x ncylinders %x\n",
lp->d_secsize, lp->d_nsectors, lp->d_ntracks, lp->d_ncylinders);
printf("Num partitions %x\n", lp->d_npartitions);
for (i = 0; i < lp->d_npartitions; i++) {
struct partition *part = &lp->d_partitions[i];
const char *fstyp = fstypenames[part->p_fstype];
printf("%c: size %10x offset %10x type %7s frag %5x cpg %3x\n",
'a' + i, part->p_size, part->p_offset, fstyp,
part->p_frag, part->p_cpg);
}
}
static void
printclp(struct cpu_disklabel *clp, const char *str)
{
int maxp, i;
printf("%s\n", str);
printf("magic1 %lx\n", clp->magic1);
printf("magic2 %lx\n", clp->magic2);
printf("typename %s\n", clp->vid_vd);
printf("secsize %x nsect %x ntrack %x ncylinders %x\n",
clp->cfg_psm, clp->cfg_spt, clp->cfg_hds, clp->cfg_trk);
printf("Num partitions %x\n", clp->partitions);
maxp = clp->partitions < 16 ? clp->partitions : 16;
for (i = 0; i < maxp; i++) {
struct partition *part;
const char *fstyp;
if (i < 4) {
part = (void *)&clp->vid_4[0];
part = &part[i];
} else {
part = (void *)&clp->cfg_4[0];
part = &part[i-4];
}
fstyp = fstypenames[part->p_fstype];
printf("%c: size %10x offset %10x type %7s frag %5x cpg %3x\n",
'a' + i, part->p_size, part->p_offset, fstyp,
part->p_frag, part->p_cpg);
}
}
#endif