diff options
author | Andrey A. Chernov <ache@FreeBSD.org> | 1996-02-13 03:46:48 +0000 |
---|---|---|
committer | Andrey A. Chernov <ache@FreeBSD.org> | 1996-02-13 03:46:48 +0000 |
commit | fa2e3e489171cd839abd497c7fa1782db4cffd15 (patch) | |
tree | 09f5756501be1f966721dbe6d22fa337c4ee49ef /sys/scsi | |
parent | 52be2bc34c5511122d31846ea0b9f6d8d5887a98 (diff) | |
download | src-fa2e3e489171cd839abd497c7fa1782db4cffd15.tar.gz src-fa2e3e489171cd839abd497c7fa1782db4cffd15.zip |
Physically ask for leadout entry instead of asking of
last_track + 1 entry, some drives don't understand it
Notes
Notes:
svn path=/head/; revision=14075
Diffstat (limited to 'sys/scsi')
-rw-r--r-- | sys/scsi/cd.c | 61 |
1 files changed, 39 insertions, 22 deletions
diff --git a/sys/scsi/cd.c b/sys/scsi/cd.c index 48ebf940abd3..e934caeb4a2e 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); } |