summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>2001-03-27 10:22:50 +0000
committersos <sos@FreeBSD.org>2001-03-27 10:22:50 +0000
commit27b491435b5af71a9b47047589a2d7bb2e49affc (patch)
tree3b11d5fc78033d6518073a383793e40ca6d42e90 /sys/dev
parent0d4e5754e50ad6be82dcd99f0c50b14e4584e60f (diff)
downloadFreeBSD-src-27b491435b5af71a9b47047589a2d7bb2e49affc.zip
FreeBSD-src-27b491435b5af71a9b47047589a2d7bb2e49affc.tar.gz
Use PLAY_MSF instead of PLAY_BIG when doing audio play.
The fixes the problem of PLAY_BIG not being implemented on some modern drives. The problem now is that some old drives use BSD encoding in the MSF case, which they dont tell, and which is also not according to spec *sigh*. Hopefully there are not too many of those still alive, or I hereby grant license to kill the firmware writers that wrote the mess.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ata/atapi-all.c3
-rw-r--r--sys/dev/ata/atapi-all.h3
-rw-r--r--sys/dev/ata/atapi-cd.c61
3 files changed, 36 insertions, 31 deletions
diff --git a/sys/dev/ata/atapi-all.c b/sys/dev/ata/atapi-all.c
index dc4c99b..105e802 100644
--- a/sys/dev/ata/atapi-all.c
+++ b/sys/dev/ata/atapi-all.c
@@ -707,6 +707,7 @@ atapi_cmd2str(u_int8_t cmd)
case 0x3c: return ("READ_BUFFER");
case 0x42: return ("READ_SUBCHANNEL");
case 0x43: return ("READ_TOC");
+ case 0x45: return ("PLAY_10");
case 0x47: return ("PLAY_MSF");
case 0x48: return ("PLAY_TRACK");
case 0x4b: return ("PAUSE");
@@ -724,7 +725,7 @@ atapi_cmd2str(u_int8_t cmd)
case 0xa1: return ("BLANK_CMD");
case 0xa3: return ("SEND_KEY");
case 0xa4: return ("REPORT_KEY");
- case 0xa5: return ("PLAY_BIG");
+ case 0xa5: return ("PLAY_12");
case 0xa6: return ("LOAD_UNLOAD");
case 0xad: return ("READ_DVD_STRUCTURE");
case 0xb4: return ("PLAY_CD");
diff --git a/sys/dev/ata/atapi-all.h b/sys/dev/ata/atapi-all.h
index fd7c188..bbd4a7c 100644
--- a/sys/dev/ata/atapi-all.h
+++ b/sys/dev/ata/atapi-all.h
@@ -92,6 +92,7 @@
#define ATAPI_READ_BUFFER 0x3c /* read device buffer */
#define ATAPI_READ_SUBCHANNEL 0x42 /* get subchannel info */
#define ATAPI_READ_TOC 0x43 /* get table of contents */
+#define ATAPI_PLAY_10 0x45 /* play by lba */
#define ATAPI_PLAY_MSF 0x47 /* play by MSF address */
#define ATAPI_PLAY_TRACK 0x48 /* play by track number */
#define ATAPI_PAUSE 0x4b /* pause audio operation */
@@ -109,7 +110,7 @@
#define ATAPI_BLANK 0xa1 /* blank the media */
#define ATAPI_SEND_KEY 0xa3 /* send DVD key structure */
#define ATAPI_REPORT_KEY 0xa4 /* get DVD key structure */
-#define ATAPI_PLAY_BIG 0xa5 /* play by lba */
+#define ATAPI_PLAY_12 0xa5 /* play by lba */
#define ATAPI_LOAD_UNLOAD 0xa6 /* changer control command */
#define ATAPI_READ_STRUCTURE 0xad /* get DVD structure */
#define ATAPI_PLAY_CD 0xb4 /* universal play command */
diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c
index d2a1591..651f00c 100644
--- a/sys/dev/ata/atapi-cd.c
+++ b/sys/dev/ata/atapi-cd.c
@@ -76,6 +76,7 @@ static void lba2msf(u_int32_t, u_int8_t *, u_int8_t *, u_int8_t *);
static u_int32_t msf2lba(u_int8_t, u_int8_t, u_int8_t);
static int acd_done(struct atapi_request *);
static void acd_read_toc(struct acd_softc *);
+static int acd_play(struct acd_softc *, int, int);
static int acd_setchan(struct acd_softc *, u_int8_t, u_int8_t, u_int8_t, u_int8_t);
static void acd_select_slot(struct acd_softc *);
static int acd_open_track(struct acd_softc *, struct cdr_track *);
@@ -787,40 +788,31 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case CDIOCPLAYMSF:
{
struct ioc_play_msf *args = (struct ioc_play_msf *)addr;
- int8_t ccb[16] = { ATAPI_PLAY_MSF, 0, 0,
- args->start_m, args->start_s, args->start_f,
- args->end_m, args->end_s, args->end_f,
- 0, 0, 0, 0, 0, 0, 0 };
- error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 10, NULL, NULL);
+ error =
+ acd_play(cdp,
+ msf2lba(args->start_m, args->start_s, args->start_f),
+ msf2lba(args->end_m, args->end_s, args->end_f));
break;
}
case CDIOCPLAYBLOCKS:
{
struct ioc_play_blocks *args = (struct ioc_play_blocks *)addr;
- int8_t ccb[16] = { ATAPI_PLAY_BIG, 0,
- args->blk>>24, args->blk>>16, args->blk>>8,
- args->blk, args->len>>24, args->len>>16,
- args->len>>8, args->len,
- 0, 0, 0, 0, 0, 0 };
- error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 10, NULL, NULL);
+ error = acd_play(cdp, args->blk, args->blk + args->len);
break;
}
case CDIOCPLAYTRACKS:
{
struct ioc_play_track *args = (struct ioc_play_track *)addr;
- u_int start, len;
int t1, t2;
- int8_t ccb[16];
if (!cdp->toc.hdr.ending_track) {
error = EIO;
break;
}
-
if (args->end_track < cdp->toc.hdr.ending_track + 1)
++args->end_track;
if (args->end_track > cdp->toc.hdr.ending_track + 1)
@@ -831,21 +823,8 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = EINVAL;
break;
}
- start = ntohl(cdp->toc.tab[t1].addr.lba);
- len = ntohl(cdp->toc.tab[t2].addr.lba) - start;
-
- bzero(ccb, sizeof(ccb));
- ccb[0] = ATAPI_PLAY_BIG;
- ccb[2] = start>>24;
- ccb[3] = start>>16;
- ccb[4] = start>>8;
- ccb[5] = start;
- ccb[6] = len>>24;
- ccb[7] = len>>16;
- ccb[8] = len>>8;
- ccb[9] = len;
-
- error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 10, NULL, NULL);
+ error = acd_play(cdp, ntohl(cdp->toc.tab[t1].addr.lba),
+ ntohl(cdp->toc.tab[t2].addr.lba));
break;
}
@@ -1340,6 +1319,30 @@ acd_read_toc(struct acd_softc *cdp)
#endif
}
+static int
+acd_play(struct acd_softc *cdp, int start, int end)
+{
+ int8_t ccb[16];
+
+ bzero(ccb, sizeof(ccb));
+#if 1
+ ccb[0] = ATAPI_PLAY_MSF;
+ lba2msf(start, &ccb[3], &ccb[4], &ccb[5]);
+ lba2msf(end, &ccb[6], &ccb[7], &ccb[8]);
+#else
+ ccb[0] = ATAPI_PLAY_12;
+ ccb[2] = start>>24;
+ ccb[3] = start>>16;
+ ccb[4] = start>>8;
+ ccb[5] = start;
+ ccb[6] = (end - start)>>24;
+ ccb[7] = (end - start)>>16;
+ ccb[8] = (end - start)>>8;
+ ccb[9] = (end - start);
+#endif
+ return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 10, NULL, NULL);
+}
+
static int
acd_setchan(struct acd_softc *cdp,
u_int8_t c0, u_int8_t c1, u_int8_t c2, u_int8_t c3)
OpenPOWER on IntegriCloud