diff options
author | sos <sos@FreeBSD.org> | 1999-12-07 22:25:28 +0000 |
---|---|---|
committer | sos <sos@FreeBSD.org> | 1999-12-07 22:25:28 +0000 |
commit | 1f5f1ce072ff94bd81f7c6df33b7055f8304b035 (patch) | |
tree | 34f51ad89f627e73395ecb99b03db057246a2923 | |
parent | b4794466d10cd898a2d611bf35aa009e958089a2 (diff) | |
download | FreeBSD-src-1f5f1ce072ff94bd81f7c6df33b7055f8304b035.zip FreeBSD-src-1f5f1ce072ff94bd81f7c6df33b7055f8304b035.tar.gz |
Commit the kernel part of our DVD support. Nothing much to say really,
its just a number of new ioctl's, the rest is done in userland.
-rw-r--r-- | sys/dev/ata/atapi-all.c | 3 | ||||
-rw-r--r-- | sys/dev/ata/atapi-all.h | 3 | ||||
-rw-r--r-- | sys/dev/ata/atapi-cd.c | 278 | ||||
-rw-r--r-- | sys/dev/ata/atapi-fd.c | 6 | ||||
-rw-r--r-- | sys/fs/cd9660/cd9660_vnops.c | 30 | ||||
-rw-r--r-- | sys/isofs/cd9660/cd9660_vnops.c | 30 | ||||
-rw-r--r-- | sys/sys/dvdio.h | 103 | ||||
-rw-r--r-- | sys/sys/filio.h | 1 |
8 files changed, 449 insertions, 5 deletions
diff --git a/sys/dev/ata/atapi-all.c b/sys/dev/ata/atapi-all.c index 2992e2a..8b8643a 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 7fa123a..a8c7b93 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 cc18ecf..9dedf7c 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 3872b54..3fbdfd5 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; } diff --git a/sys/fs/cd9660/cd9660_vnops.c b/sys/fs/cd9660/cd9660_vnops.c index abb4d6b..2f93731 100644 --- a/sys/fs/cd9660/cd9660_vnops.c +++ b/sys/fs/cd9660/cd9660_vnops.c @@ -51,6 +51,7 @@ #include <sys/malloc.h> #include <sys/dirent.h> #include <sys/unistd.h> +#include <sys/filio.h> #include <vm/vm.h> #include <vm/vm_zone.h> @@ -63,6 +64,7 @@ static int cd9660_setattr __P((struct vop_setattr_args *)); static int cd9660_access __P((struct vop_access_args *)); static int cd9660_getattr __P((struct vop_getattr_args *)); +static int cd9660_ioctl __P((struct vop_ioctl_args *)); static int cd9660_pathconf __P((struct vop_pathconf_args *)); static int cd9660_read __P((struct vop_read_args *)); struct isoreaddir; @@ -255,6 +257,33 @@ cd9660_getattr(ap) } /* + * Vnode op for ioctl. + */ +static int +cd9660_ioctl(ap) + struct vop_ioctl_args /* { + struct vnode *a_vp; + int a_command; + caddr_t a_data; + int a_fflag; + struct ucred *a_cred; + struct proc *a_p; + } */ *ap; +{ + struct vnode *vp = ap->a_vp; + struct iso_node *ip = VTOI(vp); + + switch (ap->a_command) { + + case FIOGETLBA: + *(int *)(ap->a_data) = ip->iso_start; + return 0; + default: + return (ENOTTY); + } +} + +/* * Vnode op for reading. */ static int @@ -857,6 +886,7 @@ static struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = { { &vop_cachedlookup_desc, (vop_t *) cd9660_lookup }, { &vop_getattr_desc, (vop_t *) cd9660_getattr }, { &vop_inactive_desc, (vop_t *) cd9660_inactive }, + { &vop_ioctl_desc, (vop_t *) cd9660_ioctl }, { &vop_islocked_desc, (vop_t *) vop_stdislocked }, { &vop_lock_desc, (vop_t *) vop_stdlock }, { &vop_lookup_desc, (vop_t *) vfs_cache_lookup }, diff --git a/sys/isofs/cd9660/cd9660_vnops.c b/sys/isofs/cd9660/cd9660_vnops.c index abb4d6b..2f93731 100644 --- a/sys/isofs/cd9660/cd9660_vnops.c +++ b/sys/isofs/cd9660/cd9660_vnops.c @@ -51,6 +51,7 @@ #include <sys/malloc.h> #include <sys/dirent.h> #include <sys/unistd.h> +#include <sys/filio.h> #include <vm/vm.h> #include <vm/vm_zone.h> @@ -63,6 +64,7 @@ static int cd9660_setattr __P((struct vop_setattr_args *)); static int cd9660_access __P((struct vop_access_args *)); static int cd9660_getattr __P((struct vop_getattr_args *)); +static int cd9660_ioctl __P((struct vop_ioctl_args *)); static int cd9660_pathconf __P((struct vop_pathconf_args *)); static int cd9660_read __P((struct vop_read_args *)); struct isoreaddir; @@ -255,6 +257,33 @@ cd9660_getattr(ap) } /* + * Vnode op for ioctl. + */ +static int +cd9660_ioctl(ap) + struct vop_ioctl_args /* { + struct vnode *a_vp; + int a_command; + caddr_t a_data; + int a_fflag; + struct ucred *a_cred; + struct proc *a_p; + } */ *ap; +{ + struct vnode *vp = ap->a_vp; + struct iso_node *ip = VTOI(vp); + + switch (ap->a_command) { + + case FIOGETLBA: + *(int *)(ap->a_data) = ip->iso_start; + return 0; + default: + return (ENOTTY); + } +} + +/* * Vnode op for reading. */ static int @@ -857,6 +886,7 @@ static struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = { { &vop_cachedlookup_desc, (vop_t *) cd9660_lookup }, { &vop_getattr_desc, (vop_t *) cd9660_getattr }, { &vop_inactive_desc, (vop_t *) cd9660_inactive }, + { &vop_ioctl_desc, (vop_t *) cd9660_ioctl }, { &vop_islocked_desc, (vop_t *) vop_stdislocked }, { &vop_lock_desc, (vop_t *) vop_stdlock }, { &vop_lookup_desc, (vop_t *) vfs_cache_lookup }, diff --git a/sys/sys/dvdio.h b/sys/sys/dvdio.h new file mode 100644 index 0000000..667a8e5 --- /dev/null +++ b/sys/sys/dvdio.h @@ -0,0 +1,103 @@ +/*- + * Copyright (c) 1999 Søren Schmidt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +struct dvd_layer { + u_int8_t book_type :4; + u_int8_t book_version :4; + u_int8_t disc_size :4; + u_int8_t max_rate :4; + u_int8_t nlayers :2; + u_int8_t track_path :1; + u_int8_t layer_type :4; + u_int8_t linear_density :4; + u_int8_t track_density :4; + u_int8_t bca :1; + u_int32_t start_sector; + u_int32_t end_sector; + u_int32_t end_sector_l0; +}; + +struct dvd_struct { + u_char format; + u_char layer_num; + u_char cpst; + u_char rmi; + u_int8_t agid :2; + u_int32_t length; + u_char data[2048]; +}; + +struct dvd_authinfo { + unsigned char format; + u_int8_t agid :2; + u_int8_t asf :1; + u_int8_t cpm :1; + u_int8_t cp_sec :1; + u_int8_t cgms :2; + u_int8_t reg_type :2; + u_int8_t vend_rsts :3; + u_int8_t user_rsts :3; + u_int8_t region; + u_int8_t rpc_scheme; + u_int32_t lba; + u_char keychal[10]; +}; + +#define DVDIOCREPORTKEY _IOWR('c', 32, struct dvd_authinfo) +#define DVDIOCSENDKEY _IOWR('c', 33, struct dvd_authinfo) +#define DVDIOCREADSTRUCTURE _IOWR('c', 34, struct dvd_struct) + +#define DVD_STRUCT_PHYSICAL 0x00 +#define DVD_STRUCT_COPYRIGHT 0x01 +#define DVD_STRUCT_DISCKEY 0x02 +#define DVD_STRUCT_BCA 0x03 +#define DVD_STRUCT_MANUFACT 0x04 +#define DVD_STRUCT_CMI 0x05 +#define DVD_STRUCT_PROTDISCID 0x06 +#define DVD_STRUCT_DISCKEYBLOCK 0x07 +#define DVD_STRUCT_DDS 0x08 +#define DVD_STRUCT_RMD_LAST 0x0C +#define DVD_STRUCT_RMD_RMA 0x0D +#define DVD_STRUCT_PRERECORDED 0x0E +#define DVD_STRUCT_UNIQUEID 0x0F +#define DVD_STRUCT_DCB 0x30 +#define DVD_STRUCT_LIST 0xFF + +#define DVD_REPORT_AGID 0 +#define DVD_REPORT_CHALLENGE 1 +#define DVD_REPORT_KEY1 2 +#define DVD_REPORT_TITLE_KEY 4 +#define DVD_REPORT_ASF 5 +#define DVD_REPORT_RPC 8 +#define DVD_INVALIDATE_AGID 0x3f + +#define DVD_SEND_CHALLENGE 1 +#define DVD_SEND_KEY2 3 +#define DVD_SEND_RPC 6 diff --git a/sys/sys/filio.h b/sys/sys/filio.h index 07dff62..044a076 100644 --- a/sys/sys/filio.h +++ b/sys/sys/filio.h @@ -53,5 +53,6 @@ #define FIOSETOWN _IOW('f', 124, int) /* set owner */ #define FIOGETOWN _IOR('f', 123, int) /* get owner */ #define FIODTYPE _IOR('f', 122, int) /* get d_flags type part */ +#define FIOGETLBA _IOR('f', 121, int) /* get start blk # */ #endif /* !_SYS_FILIO_H_ */ |