summaryrefslogtreecommitdiffstats
path: root/sys/dev/ata/atapi-cd.c
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>2001-09-10 11:43:20 +0000
committersos <sos@FreeBSD.org>2001-09-10 11:43:20 +0000
commit88f682cd6ba8173bb8d16cd11d9d86dac5fcfa63 (patch)
treee62c1f87e8275c7d0c3ab3395dd7a15236748363 /sys/dev/ata/atapi-cd.c
parentb383ffdffaa2b6777cebd03576ae5f749df0d49f (diff)
downloadFreeBSD-src-88f682cd6ba8173bb8d16cd11d9d86dac5fcfa63.zip
FreeBSD-src-88f682cd6ba8173bb8d16cd11d9d86dac5fcfa63.tar.gz
Add kernel side support for DAO burning.
Diffstat (limited to 'sys/dev/ata/atapi-cd.c')
-rw-r--r--sys/dev/ata/atapi-cd.c109
1 files changed, 83 insertions, 26 deletions
diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c
index 2305580..31d86e9 100644
--- a/sys/dev/ata/atapi-cd.c
+++ b/sys/dev/ata/atapi-cd.c
@@ -79,12 +79,13 @@ 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_disk(struct acd_softc *);
-static int acd_close_disk(struct acd_softc *, int);
-static int acd_open_track(struct acd_softc *, struct cdr_track *);
-static int acd_close_track(struct acd_softc *);
+static int acd_init_writer(struct acd_softc *, int);
+static int acd_fixate(struct acd_softc *, int);
+static int acd_init_track(struct acd_softc *, struct cdr_track *);
+static int acd_flush(struct acd_softc *);
static int acd_read_track_info(struct acd_softc *, int32_t, struct acd_track_info *);
static int acd_get_progress(struct acd_softc *, int *);
+static int acd_send_cue(struct acd_softc *, struct cdr_cuesheet *);
static int acd_report_key(struct acd_softc *, struct dvd_authinfo *);
static int acd_send_key(struct acd_softc *, struct dvd_authinfo *);
static int acd_read_structure(struct acd_softc *, struct dvd_struct *);
@@ -95,7 +96,7 @@ static int acd_start_stop(struct acd_softc *, int);
static int acd_pause_resume(struct acd_softc *, int);
static int acd_mode_sense(struct acd_softc *, int, caddr_t, int);
static int acd_mode_select(struct acd_softc *, caddr_t, int);
-static int acd_set_speed(struct acd_softc *, int);
+static int acd_set_speed(struct acd_softc *, int, int);
static void acd_get_cap(struct acd_softc *);
/* internal vars */
@@ -975,24 +976,28 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
break;
- case CDRIOCOPENDISK:
- error = acd_open_disk(cdp);
+ case CDRIOCINITWRITER:
+ error = acd_init_writer(cdp, (*(int *)addr));
break;
- case CDRIOCOPENTRACK:
- error = acd_open_track(cdp, (struct cdr_track *)addr);
+ case CDRIOCINITTRACK:
+ error = acd_init_track(cdp, (struct cdr_track *)addr);
break;
- case CDRIOCCLOSETRACK:
- error = acd_close_track(cdp);
+ case CDRIOCFLUSH:
+ error = acd_flush(cdp);
break;
- case CDRIOCCLOSEDISK:
- error = acd_close_disk(cdp, (*(int *)addr));
+ case CDRIOCFIXATE:
+ error = acd_fixate(cdp, (*(int *)addr));
+ break;
+
+ case CDRIOCREADSPEED:
+ error = acd_set_speed(cdp, 177 * (*(int *)addr), -1);
break;
case CDRIOCWRITESPEED:
- error = acd_set_speed(cdp, (*(int *)addr));
+ error = acd_set_speed(cdp, -1, 177 * (*(int *)addr));
break;
case CDRIOCGETBLOCKSIZE:
@@ -1007,6 +1012,10 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = acd_get_progress(cdp, (int *)addr);
break;
+ case CDRIOCSENDCUE:
+ error = acd_send_cue(cdp, (struct cdr_cuesheet *)addr);
+ break;
+
case DVDIOCREPORTKEY:
if (!cdp->cap.read_dvdrom)
error = EINVAL;
@@ -1115,6 +1124,7 @@ acd_start(struct atapi_softc *atp)
/* reject all queued entries if media changed */
if (cdp->atp->flags & ATAPI_F_MEDIA_CHANGED) {
+printf("reject due to media change\n");
biofinish(bp, NULL, EIO);
return;
}
@@ -1167,8 +1177,9 @@ acd_start(struct atapi_softc *atp)
ccb[9] = 0x10;
}
}
- else
+ else
ccb[0] = ATAPI_WRITE_BIG;
+
ccb[1] = 0;
ccb[2] = lba>>24;
ccb[3] = lba>>16;
@@ -1251,7 +1262,7 @@ acd_read_toc(struct acd_softc *cdp)
bzero(ccb, sizeof(ccb));
ccb[0] = ATAPI_READ_CAPACITY;
if (atapi_queue_cmd(cdp->atp, ccb, (caddr_t)sizes, sizeof(sizes),
- ATPR_F_READ, 30, NULL, NULL)) {
+ ATPR_F_READ | ATPR_F_QUIET, 30, NULL, NULL)) {
bzero(&cdp->toc, sizeof(cdp->toc));
return;
}
@@ -1394,9 +1405,11 @@ acd_select_slot(struct acd_softc *cdp)
}
static int
-acd_open_disk(struct acd_softc *cdp)
+acd_init_writer(struct acd_softc *cdp, int test_write)
{
+ struct write_param param;
int8_t ccb[16];
+ int error;
bzero(ccb, sizeof(ccb));
ccb[0] = ATAPI_REZERO;
@@ -1404,11 +1417,27 @@ acd_open_disk(struct acd_softc *cdp)
ccb[0] = ATAPI_SEND_OPC_INFO;
ccb[1] = 0x01;
atapi_queue_cmd(cdp->atp, ccb, NULL, 0, ATPR_F_QUIET, 30, NULL, NULL);
- return 0;
+
+ if ((error = acd_mode_sense(cdp, ATAPI_CDROM_WRITE_PARAMETERS_PAGE,
+ (caddr_t)&param, sizeof(param))))
+ return error;
+ param.data_length = 0;
+ param.page_code = ATAPI_CDROM_WRITE_PARAMETERS_PAGE;
+ param.page_length = 0x32;
+ param.test_write = test_write ? 1 : 0;
+ param.write_type = CDR_WTYPE_SESSION;
+ param.session_type = CDR_SESS_NONE;
+ param.fp = 0;
+ param.packet_size = 0;
+ param.track_mode = CDR_TMODE_AUDIO;
+ param.datablock_type = CDR_DB_RAW;
+ param.session_format = CDR_SESS_CDROM;
+
+ return acd_mode_select(cdp, (caddr_t)&param, param.page_length + 10);
}
static int
-acd_close_disk(struct acd_softc *cdp, int multisession)
+acd_fixate(struct acd_softc *cdp, int multisession)
{
int8_t ccb[16] = { ATAPI_CLOSE_TRACK, 0x01, 0x02, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 };
@@ -1449,7 +1478,7 @@ acd_close_disk(struct acd_softc *cdp, int multisession)
}
static int
-acd_open_track(struct acd_softc *cdp, struct cdr_track *track)
+acd_init_track(struct acd_softc *cdp, struct cdr_track *track)
{
struct write_param param;
int error;
@@ -1529,12 +1558,12 @@ acd_open_track(struct acd_softc *cdp, struct cdr_track *track)
}
static int
-acd_close_track(struct acd_softc *cdp)
+acd_flush(struct acd_softc *cdp)
{
int8_t ccb[16] = { ATAPI_SYNCHRONIZE_CACHE, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 };
- return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 60, NULL, NULL);
+ return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, ATPR_F_QUIET, 60, NULL,NULL);
}
static int
@@ -1582,6 +1611,35 @@ acd_get_progress(struct acd_softc *cdp, int *finished)
}
static int
+acd_send_cue(struct acd_softc *cdp, struct cdr_cuesheet *cuesheet)
+{
+ int8_t ccb[16] = { ATAPI_SEND_CUE_SHEET, 0, 0, 0, 0, 0,
+ cuesheet->len>>16, cuesheet->len>>8, cuesheet->len,
+ 0, 0, 0, 0, 0, 0, 0 };
+ int8_t *buffer;
+ int32_t error;
+#ifdef ACD_DEBUG
+ int i;
+#endif
+ buffer = malloc(cuesheet->len, M_ACD, M_NOWAIT);
+ if (!buffer)
+ return ENOMEM;
+ if ((error = copyin(cuesheet->entries, buffer, cuesheet->len)))
+ return error;
+#ifdef ACD_DEBUG
+ printf("acd: cuesheet lenght = %d\n", cuesheet->len);
+ for (i=0; i<cuesheet->len; i++)
+ if (i%8) printf(" %02x", buffer[i]);
+ else printf("\n%02x", buffer[i]);
+ printf("\n");
+#endif
+ error = atapi_queue_cmd(cdp->atp, ccb, buffer, cuesheet->len, 0, 30,
+ NULL, NULL);
+ free(buffer, M_ACD);
+ return error;
+}
+
+static int
acd_report_key(struct acd_softc *cdp, struct dvd_authinfo *ai)
{
struct {
@@ -1917,11 +1975,10 @@ acd_mode_select(struct acd_softc *cdp, caddr_t pagebuf, int pagesize)
}
static int
-acd_set_speed(struct acd_softc *cdp, int speed)
+acd_set_speed(struct acd_softc *cdp, int rdspeed, int wrspeed)
{
- int8_t ccb[16] = { ATAPI_SET_SPEED, 0, 0xff, 0xff,
- (speed * 177) >> 8, (speed * 177),
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ int8_t ccb[16] = { ATAPI_SET_SPEED, 0, rdspeed >> 8, rdspeed,
+ wrspeed >> 8, wrspeed, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int error;
error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL);
OpenPOWER on IntegriCloud