summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/scsi/cd.c110
1 files changed, 98 insertions, 12 deletions
diff --git a/sys/scsi/cd.c b/sys/scsi/cd.c
index 75e089270f4..d8f8a4443a6 100644
--- a/sys/scsi/cd.c
+++ b/sys/scsi/cd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cd.c,v 1.44 1999/09/25 03:28:48 deraadt Exp $ */
+/* $OpenBSD: cd.c,v 1.45 1999/10/14 05:23:02 deraadt Exp $ */
/* $NetBSD: cd.c,v 1.100 1997/04/02 02:29:30 mycroft Exp $ */
/*
@@ -89,6 +89,17 @@
#define CD_FRAMES 75
#define CD_SECS 60
+#define TOC_HEADER_LEN 0
+#define TOC_HEADER_STARTING_TRACK 2
+#define TOC_HEADER_ENDING_TRACK 3
+#define TOC_HEADER_SZ 4
+
+#define TOC_ENTRY_CONTROL_ADDR_TYPE 1
+#define TOC_ENTRY_TRACK 2
+#define TOC_ENTRY_MSF_LBA 4
+#define TOC_ENTRY_SZ 8
+
+
struct cd_toc {
struct ioc_toc_header header;
struct cd_toc_entry entries[MAXTRACK+1]; /* One extra for the */
@@ -1143,6 +1154,9 @@ cdgetdisklabel(dev, cd, lp, clp, spoofonly)
int spoofonly;
{
char *errstring;
+ u_int8_t hdr[TOC_HEADER_SZ], *ent, *toc = NULL;
+ u_int32_t lba, nlba;
+ int tocidx, i, n, len, is_data, data_track = -1;
bzero(lp, sizeof(struct disklabel));
bzero(clp, sizeof(struct cpu_disklabel));
@@ -1175,24 +1189,96 @@ cdgetdisklabel(dev, cd, lp, clp, spoofonly)
lp->d_bbsize = BBSIZE;
lp->d_sbsize = SBSIZE;
- lp->d_partitions[RAW_PART].p_offset = 0;
- lp->d_partitions[RAW_PART].p_size =
- lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
- 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);
+ /* The raw partition is special. */
+ 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;
+
/*
- * Call the generic disklabel extraction routine
+ * Read the TOC and loop throught the individual tracks and lay them
+ * out in our disklabel. If there is a data track, call the generic
+ * disklabel read routine. XXX should we move all data tracks up front
+ * before any other tracks?
*/
- errstring = readdisklabel(CDLABELDEV(dev), cdstrategy, lp, clp,
- spoofonly);
- if (errstring) {
- /*printf("%s: %s\n", cd->sc_dev.dv_xname, errstring);*/
+ if (cd_read_toc(cd, 0, 0, hdr, TOC_HEADER_SZ, 0))
return;
+ n = hdr[TOC_HEADER_ENDING_TRACK] - hdr[TOC_HEADER_STARTING_TRACK] + 1;
+ /* n + 1 because of leadout track */
+ len = TOC_HEADER_SZ + (n + 1) * TOC_ENTRY_SZ;
+ MALLOC(toc, u_int8_t *, len, M_TEMP, M_WAITOK);
+ if (cd_read_toc (cd, CD_LBA_FORMAT, 0, toc, len, 0))
+ goto done;
+
+ /* Create the partition table. */
+ ent = toc + TOC_HEADER_SZ;
+ lba = ((cd->sc_link->quirks & ADEV_LITTLETOC) ?
+ ent[TOC_ENTRY_MSF_LBA] | ent[TOC_ENTRY_MSF_LBA + 1] << 8 |
+ ent[TOC_ENTRY_MSF_LBA + 2] << 16 |
+ ent[TOC_ENTRY_MSF_LBA + 3] << 24 :
+ ent[TOC_ENTRY_MSF_LBA] << 24 | ent[TOC_ENTRY_MSF_LBA + 1] << 16 |
+ ent[TOC_ENTRY_MSF_LBA + 2] << 8 | ent[TOC_ENTRY_MSF_LBA + 3]);
+
+ i = 0;
+ for (tocidx = hdr[TOC_HEADER_STARTING_TRACK];
+ tocidx <= hdr[TOC_HEADER_ENDING_TRACK];
+ tocidx++) {
+ ent += TOC_ENTRY_SZ;
+ nlba = ((cd->sc_link->quirks & ADEV_LITTLETOC) ?
+ ent[TOC_ENTRY_MSF_LBA] |
+ ent[TOC_ENTRY_MSF_LBA + 1] << 8 |
+ ent[TOC_ENTRY_MSF_LBA + 2] << 16 |
+ ent[TOC_ENTRY_MSF_LBA + 3] << 24 :
+ ent[TOC_ENTRY_MSF_LBA] << 24 |
+ ent[TOC_ENTRY_MSF_LBA + 1] << 16 |
+ ent[TOC_ENTRY_MSF_LBA + 2] << 8 |
+ ent[TOC_ENTRY_MSF_LBA + 3]);
+ is_data = ent[TOC_ENTRY_CONTROL_ADDR_TYPE] & 4;
+
+ lp->d_partitions[i].p_fstype =
+ is_data ? FS_UNUSED : FS_OTHER;
+ lp->d_partitions[i].p_offset = lba;
+ lp->d_partitions[i].p_size = nlba - lba;
+ lba = nlba;
+
+ if (is_data) {
+ if (data_track == -1)
+ data_track = i;
+
+ i++;
+ if (i == RAW_PART)
+ i++;
+
+ if (i >= MAXPARTITIONS)
+ break;
+ }
+ }
+
+ if (i < MAXPARTITIONS)
+ bzero(&lp->d_partitions[i], sizeof(lp->d_partitions[i]));
+
+ lp->d_npartitions = max(RAW_PART, i - 1) + 1;
+
+done:
+ if (toc)
+ FREE(toc, M_TEMP);
+
+ /* We have a data track, look in there for a real disklabel. */
+ if (data_track != -1) {
+#if 0
+ /* This might not necessarily work */
+ errstring = readdisklabel(MAKECDDEV(major(dev), CDUNIT(dev),
+ data_track), cdstrategy, lp, clp, spoofonly);
+#else
+ errstring = readdisklabel(CDLABELDEV(dev),
+ cdstrategy, lp, clp, spoofonly);
+#endif
+ /*if (errstring)
+ printf("%s: %s\n", cd->sc_dev.dv_xname, errstring);*/
}
}