summaryrefslogtreecommitdiffstats
path: root/sys/scsi/cd.c
diff options
context:
space:
mode:
authorache <ache@FreeBSD.org>1996-02-13 03:46:48 +0000
committerache <ache@FreeBSD.org>1996-02-13 03:46:48 +0000
commit63aca4a0d96cf6dc367174d2b60720f70e7f417a (patch)
tree09f5756501be1f966721dbe6d22fa337c4ee49ef /sys/scsi/cd.c
parent5ab0a6f9b3ab538a162c42bfe4d84727d20da20c (diff)
downloadFreeBSD-src-63aca4a0d96cf6dc367174d2b60720f70e7f417a.zip
FreeBSD-src-63aca4a0d96cf6dc367174d2b60720f70e7f417a.tar.gz
Physically ask for leadout entry instead of asking of
last_track + 1 entry, some drives don't understand it
Diffstat (limited to 'sys/scsi/cd.c')
-rw-r--r--sys/scsi/cd.c61
1 files changed, 39 insertions, 22 deletions
diff --git a/sys/scsi/cd.c b/sys/scsi/cd.c
index 48ebf94..e934cae 100644
--- a/sys/scsi/cd.c
+++ b/sys/scsi/cd.c
@@ -91,6 +91,7 @@ static int32 cdstrats, cdqueues;
#define SECSIZE 2048 /* XXX */ /* default only */
#define CDOUTSTANDING 2
#define CDRETRIES 1
+#define LEADOUT 0xaa /* leadout toc entry */
#define PARTITION(z) (minor(z) & 0x07)
#define RAW_PART 2
@@ -195,16 +196,6 @@ cd_registerdev(int unit)
}
}
-static inline void lba2msf (int lba, u_char *m, u_char *s, u_char *f)
-{
- lba += 150; /* offset of first logical frame */
- lba &= 0xffffff; /* negative lbas use only 24 bits */
- *m = lba / (60 * 75);
- lba %= (60 * 75);
- *s = lba / 75;
- *f = lba % 75;
-}
-
/*
* The routine called by the low level scsi routine when it discovers
* A device suitable for this driver
@@ -762,14 +753,18 @@ cd_ioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p,
break;
case CDIOREADTOCENTRYS:
{
- struct cd_toc {
+ struct {
struct ioc_toc_header header;
struct cd_toc_entry entries[100];
} data;
+ struct {
+ struct ioc_toc_header header;
+ struct cd_toc_entry entry;
+ } lead;
struct ioc_read_toc_entry *te =
(struct ioc_read_toc_entry *) addr;
struct ioc_toc_header *th;
- u_int32 len;
+ u_int32 len, readlen, idx, num;
u_int32 starting_track = te->starting_track;
if ( te->data_len < sizeof(struct cd_toc_entry)
@@ -789,7 +784,7 @@ cd_ioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p,
if (starting_track == 0)
starting_track = th->starting_track;
- else if (starting_track == 170)
+ else if (starting_track == LEADOUT)
starting_track = th->ending_track + 1;
else if (starting_track < th->starting_track ||
starting_track > th->ending_track + 1) {
@@ -797,21 +792,43 @@ cd_ioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p,
break;
}
- len = ((th->ending_track + 1 - starting_track) + 1) *
- sizeof(struct cd_toc_entry);
- if (te->data_len < len)
+ /* calculate reading length without leadout entry */
+ readlen = (th->ending_track - starting_track + 1) *
+ sizeof(struct cd_toc_entry);
+
+ /* and with leadout entry */
+ len = readlen + sizeof(struct cd_toc_entry);
+ if (te->data_len < len) {
len = te->data_len;
+ if (readlen > len)
+ readlen = len;
+ }
if (len > sizeof(data.entries)) {
error = EINVAL;
break;
}
+ num = len / sizeof(struct cd_toc_entry);
+
+ if (readlen > 0) {
+ error = cd_read_toc(unit, te->address_format,
+ starting_track,
+ (struct cd_toc_entry *)&data,
+ readlen + sizeof (*th));
+ if (error)
+ break;
+ }
- error = cd_read_toc(unit, te->address_format,
- starting_track,
- (struct cd_toc_entry *)&data,
- len + sizeof (*th));
- if (error)
- break;
+ /* make leadout entry if needed */
+ idx = starting_track + num - 1;
+ if (idx == th->ending_track + 1) {
+ error = cd_read_toc(unit, te->address_format,
+ LEADOUT,
+ (struct cd_toc_entry *)&lead,
+ sizeof(lead));
+ if (error)
+ break;
+ data.entries[idx - starting_track] = lead.entry;
+ }
error = copyout(data.entries, te->data, len);
}
OpenPOWER on IntegriCloud