aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/ata
diff options
context:
space:
mode:
authorSøren Schmidt <sos@FreeBSD.org>1999-12-07 22:25:28 +0000
committerSøren Schmidt <sos@FreeBSD.org>1999-12-07 22:25:28 +0000
commitcb2a8dffa0a79ce0096335ff68f3dabd716626d5 (patch)
tree48f106ba8968fa5430d241fce1358592ea458176 /sys/dev/ata
parentf3a2511a25ce33bae3166c730959a167b94fa0eb (diff)
Notes
Diffstat (limited to 'sys/dev/ata')
-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.c278
-rw-r--r--sys/dev/ata/atapi-fd.c6
4 files changed, 285 insertions, 5 deletions
diff --git a/sys/dev/ata/atapi-all.c b/sys/dev/ata/atapi-all.c
index 2992e2a355426..8b8643a4ffc0f 100644
--- a/sys/dev/ata/atapi-all.c
+++ b/sys/dev/ata/atapi-all.c
@@ -706,7 +706,10 @@ atapi_cmd2str(u_int8_t cmd)
case 0x4b: return ("PAUSE");
case 0x48: return ("PLAY_TRACK");
case 0xa1: return ("BLANK_CMD");
+ case 0xa3: return ("SEND_KEY");
+ case 0xa4: return ("REPORT_KEY");
case 0xa5: return ("PLAY_BIG");
+ case 0xad: return ("READ_DVD_STRUCTURE");
case 0xb4: return ("PLAY_CD");
case 0xbd: return ("MECH_STATUS");
case 0xbe: return ("READ_CD");
diff --git a/sys/dev/ata/atapi-all.h b/sys/dev/ata/atapi-all.h
index 7fa123acb31c3..a8c7b9382408e 100644
--- a/sys/dev/ata/atapi-all.h
+++ b/sys/dev/ata/atapi-all.h
@@ -99,8 +99,11 @@
#define ATAPI_MODE_SENSE_BIG 0x5a /* get device parameters */
#define ATAPI_CLOSE_TRACK 0x5b /* close track/session */
#define ATAPI_BLANK 0xa1 /* blank the media */
+#define ATAPI_SEND_KEY 0xa3
+#define ATAPI_REPORT_KEY 0xa4
#define ATAPI_PLAY_BIG 0xa5 /* play by lba */
#define ATAPI_LOAD_UNLOAD 0xa6 /* changer control command */
+#define ATAPI_READ_STRUCTURE 0xad
#define ATAPI_PLAY_CD 0xb4 /* universal play command */
#define ATAPI_SET_SPEED 0xbb /* set drive speed */
#define ATAPI_MECH_STATUS 0xbd /* get changer status */
diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c
index cc18ecfbc340d..9dedf7c6e771b 100644
--- a/sys/dev/ata/atapi-cd.c
+++ b/sys/dev/ata/atapi-cd.c
@@ -39,6 +39,7 @@
#include <sys/devicestat.h>
#include <sys/cdio.h>
#include <sys/wormio.h>
+#include <sys/dvdio.h>
#include <sys/fcntl.h>
#include <sys/conf.h>
#include <sys/stat.h>
@@ -87,6 +88,9 @@ static int32_t acd_open_track(struct acd_softc *, struct wormio_prepare_track *)
static int32_t acd_close_track(struct acd_softc *);
static int32_t acd_close_disk(struct acd_softc *);
static int32_t acd_read_track_info(struct acd_softc *, int32_t, struct acd_track_info*);
+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 *);
static int32_t acd_eject(struct acd_softc *, int32_t);
static int32_t acd_blank(struct acd_softc *);
static int32_t acd_prevent_allow(struct acd_softc *, int32_t);
@@ -279,7 +283,11 @@ acd_describe(struct acd_softc *cdp)
printf("%s CD-RW", comma ? "," : ""); comma = 1;
}
if (cdp->cap.cd_da) {
- printf("%s CD-DA", comma ? "," : ""); comma = 1;
+ if (cdp->cap.cd_da_stream)
+ printf("%s CD-DA stream", comma ? "," : "");
+ else
+ printf("%s CD-DA", comma ? "," : "");
+ comma = 1;
}
if (cdp->cap.read_dvdrom) {
printf("%s DVD-ROM", comma ? "," : ""); comma = 1;
@@ -984,6 +992,27 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
error = acd_blank(cdp);
break;
+ case DVDIOCREPORTKEY:
+ if (!cdp->cap.read_dvdrom)
+ error = EINVAL;
+ else
+ error = acd_report_key(cdp, (struct dvd_authinfo *)addr);
+ break;
+
+ case DVDIOCSENDKEY:
+ if (!cdp->cap.read_dvdrom)
+ error = EINVAL;
+ else
+ error = acd_send_key(cdp, (struct dvd_authinfo *)addr);
+ break;
+
+ case DVDIOCREADSTRUCTURE:
+ if (!cdp->cap.read_dvdrom)
+ error = EINVAL;
+ else
+ error = acd_read_structure(cdp, (struct dvd_struct *)addr);
+ break;
+
default:
error = ENOTTY;
}
@@ -1380,6 +1409,252 @@ acd_read_track_info(struct acd_softc *cdp,
return 0;
}
+static int
+acd_report_key(struct acd_softc *cdp, struct dvd_authinfo *ai)
+{
+ struct {
+ u_int16_t length;
+ u_char reserved[2];
+ u_char data[12];
+ } d;
+ u_int32_t lba = 0;
+ int32_t error;
+ int16_t length;
+ int8_t ccb[16];
+
+ printf("dvd_report_key: format=0x%x\n", ai->format);
+
+ switch (ai->format) {
+ case DVD_REPORT_AGID:
+ case DVD_REPORT_ASF:
+ case DVD_REPORT_RPC:
+ length = 8;
+ break;
+ case DVD_REPORT_KEY1:
+ length = 12;
+ break;
+ case DVD_REPORT_TITLE_KEY:
+ length = 12;
+ lba = ai->lba;
+ break;
+ case DVD_REPORT_CHALLENGE:
+ length = 16;
+ break;
+ case DVD_INVALIDATE_AGID:
+ length = 0;
+ break;
+ default:
+ return EINVAL;
+ }
+
+ bzero(ccb, sizeof(ccb));
+ ccb[0] = ATAPI_REPORT_KEY;
+ ccb[2] = (lba >> 24) & 0xff;
+ ccb[3] = (lba >> 16) & 0xff;
+ ccb[4] = (lba >> 8) & 0xff;
+ ccb[5] = lba & 0xff;
+ ccb[8] = (length >> 8) & 0xff;
+ ccb[9] = length & 0xff;
+ ccb[10] = (ai->agid << 6) | ai->format;
+ bzero(&d, sizeof(d));
+ d.length = htons(length - 2);
+ error = atapi_queue_cmd(cdp->atp, ccb, &d, length,
+ (ai->format == DVD_INVALIDATE_AGID) ? 0 : A_READ,
+ 10, NULL, NULL, NULL);
+ if (error)
+ return error;
+
+ switch (ai->format) {
+ case DVD_REPORT_AGID:
+ ai->agid = d.data[3] >> 6;
+ break;
+
+ case DVD_REPORT_CHALLENGE:
+ bcopy(&d.data[0], &ai->keychal[0], 10);
+ break;
+
+ case DVD_REPORT_KEY1:
+ bcopy(&d.data[0], &ai->keychal[0], 5);
+ break;
+
+ case DVD_REPORT_TITLE_KEY:
+ ai->cpm = (d.data[0] >> 7);
+ ai->cp_sec = (d.data[0] >> 6) & 0x1;
+ ai->cgms = (d.data[0] >> 4) & 0x3;
+ bcopy(&d.data[1], &ai->keychal[0], 5);
+ break;
+
+ case DVD_REPORT_ASF:
+ ai->asf = d.data[3] & 1;
+ break;
+
+ case DVD_REPORT_RPC:
+ ai->reg_type = (d.data[0] >> 6);
+ ai->vend_rsts = (d.data[0] >> 3) & 0x7;
+ ai->user_rsts = d.data[0] & 0x7;
+ break;
+
+ case DVD_INVALIDATE_AGID:
+ break;
+
+ default:
+ return EINVAL;
+ }
+ return 0;
+}
+
+static int
+acd_send_key(struct acd_softc *cdp, struct dvd_authinfo *ai)
+{
+ struct {
+ u_int16_t length;
+ u_char reserved[2];
+ u_char data[12];
+ } d;
+ int16_t length;
+ int8_t ccb[16];
+
+ printf("dvd_send_key: format=0x%x\n", ai->format);
+
+ bzero(&d, sizeof(d));
+
+ switch (ai->format) {
+ case DVD_SEND_CHALLENGE:
+ length = 16;
+ bcopy(ai->keychal, &d.data[0], 10);
+ break;
+
+ case DVD_SEND_KEY2:
+ length = 12;
+ bcopy(&ai->keychal[0], &d.data[0], 5);
+ break;
+
+ case DVD_SEND_RPC:
+ length = 8;
+ break;
+
+ default:
+ return EINVAL;
+ }
+
+ bzero(ccb, sizeof(ccb));
+ ccb[0] = ATAPI_SEND_KEY;
+ ccb[8] = (length >> 8) & 0xff;
+ ccb[9] = length & 0xff;
+ ccb[10] = (ai->agid << 6) | ai->format;
+ d.length = htons(length - 2);
+ return atapi_queue_cmd(cdp->atp, ccb, &d, length, 0, 10, NULL, NULL, NULL);
+}
+
+static int
+acd_read_structure(struct acd_softc *cdp, struct dvd_struct *s)
+{
+ struct {
+ u_int16_t length;
+ u_char reserved[2];
+ u_char data[2048];
+ } d;
+ u_int16_t length;
+ int32_t error = 0;
+ int8_t ccb[16];
+
+ printf("dvd_read_structure: format=0x%x\n", s->format);
+
+ bzero(&d, sizeof(d));
+
+ switch(s->format) {
+ case DVD_STRUCT_PHYSICAL:
+ length = 21;
+ break;
+
+ case DVD_STRUCT_COPYRIGHT:
+ length = 8;
+ break;
+
+ case DVD_STRUCT_DISCKEY:
+ length = 2052;
+ break;
+
+ case DVD_STRUCT_BCA:
+ length = 192;
+ break;
+
+ case DVD_STRUCT_MANUFACT:
+ length = 2052;
+ break;
+
+ case DVD_STRUCT_DDS:
+ case DVD_STRUCT_PRERECORDED:
+ case DVD_STRUCT_UNIQUEID:
+ case DVD_STRUCT_LIST:
+ case DVD_STRUCT_CMI:
+ case DVD_STRUCT_RMD_LAST:
+ case DVD_STRUCT_RMD_RMA:
+ case DVD_STRUCT_DCB:
+ return ENOSYS;
+
+ default:
+ return EINVAL;
+ }
+
+ bzero(ccb, sizeof(ccb));
+ ccb[0] = ATAPI_READ_STRUCTURE;
+ ccb[6] = s->layer_num;
+ ccb[7] = s->format;
+ ccb[8] = (length >> 8) & 0xff;
+ ccb[9] = length & 0xff;
+ ccb[10] = s->agid << 6;
+ d.length = htons(length - 2);
+ error = atapi_queue_cmd(cdp->atp, ccb, &d, length, A_READ, 30,
+ NULL, NULL, NULL);
+ if (error)
+ return error;
+
+ switch (s->format) {
+ case DVD_STRUCT_PHYSICAL: {
+ struct dvd_layer *layer = (struct dvd_layer *)&s->data[0];
+
+ layer->book_type = d.data[0] >> 4;
+ layer->book_version = d.data[0] & 0xf;
+ layer->disc_size = d.data[1] >> 4;
+ layer->max_rate = d.data[1] & 0xf;
+ layer->nlayers = (d.data[2] >> 5) & 3;
+ layer->track_path = (d.data[2] >> 4) & 1;
+ layer->layer_type = d.data[2] & 0xf;
+ layer->linear_density = d.data[3] >> 4;
+ layer->track_density = d.data[3] & 0xf;
+ layer->start_sector = d.data[5] << 16 | d.data[6] << 8 | d.data[7];
+ layer->end_sector = d.data[9] << 16 | d.data[10] << 8 | d.data[11];
+ layer->end_sector_l0 = d.data[13] << 16 | d.data[14] << 8 | d.data[15];
+ layer->bca = d.data[16] >> 7;
+ break;
+ }
+
+ case DVD_STRUCT_COPYRIGHT:
+ s->cpst = d.data[0];
+ s->rmi = d.data[0];
+ break;
+
+ case DVD_STRUCT_DISCKEY:
+ bcopy(&d.data[0], &s->data[0], 2048);
+ break;
+
+ case DVD_STRUCT_BCA:
+ s->length = ntohs(d.length);
+ bcopy(&d.data[0], &s->data[0], s->length);
+ break;
+
+ case DVD_STRUCT_MANUFACT:
+ s->length = ntohs(d.length);
+ bcopy(&d.data[0], &s->data[0], s->length);
+ break;
+
+ default:
+ return EINVAL;
+ }
+ return 0;
+}
+
static int32_t
acd_eject(struct acd_softc *cdp, int32_t close)
{
@@ -1485,3 +1760,4 @@ acd_set_speed(struct acd_softc *cdp, int32_t speed)
return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL, NULL);
}
+
diff --git a/sys/dev/ata/atapi-fd.c b/sys/dev/ata/atapi-fd.c
index 3872b54be182b..3fbdfd5b1305b 100644
--- a/sys/dev/ata/atapi-fd.c
+++ b/sys/dev/ata/atapi-fd.c
@@ -142,7 +142,7 @@ afd_sense(struct afd_softc *fdp)
if (error)
return error;
bcopy(buffer, &fdp->header, sizeof(struct afd_header));
- bcopy(buffer+sizeof(struct afd_header), &fdp->cap,
+ bcopy(buffer + sizeof(struct afd_header), &fdp->cap,
sizeof(struct afd_cappage));
if (fdp->cap.page_code != ATAPI_REWRITEABLE_CAP_PAGE)
return 1;
@@ -207,16 +207,14 @@ afdopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p)
if (afd_sense(fdp))
printf("afd%d: sense media type failed\n", fdp->lun);
- /* build disklabel and initilize slice tables */
label = &fdp->disk.d_label;
bzero(label, sizeof *label);
label->d_secsize = fdp->cap.sector_size;
label->d_nsectors = fdp->cap.sectors;
label->d_ntracks = fdp->cap.heads;
label->d_ncylinders = fdp->cap.cylinders;
- label->d_secpercyl = fdp->cap.heads * fdp->cap.sectors;
+ label->d_secpercyl = fdp->cap.sectors * fdp->cap.heads;
label->d_secperunit = label->d_secpercyl * fdp->cap.cylinders;
-
return 0;
}