|
Lines 725-769
Link Here
|
| 725 |
{ |
725 |
{ |
| 726 |
struct ioc_read_subchannel *args = |
726 |
struct ioc_read_subchannel *args = |
| 727 |
(struct ioc_read_subchannel *)addr; |
727 |
(struct ioc_read_subchannel *)addr; |
| 728 |
struct cd_sub_channel_info data; |
728 |
u_int8_t format; |
| 729 |
int len = args->data_len; |
729 |
int len = args->data_len; |
| 730 |
int32_t abslba, rellba; |
|
|
| 731 |
int8_t ccb[16] = { ATAPI_READ_SUBCHANNEL, 0, 0x40, 1, 0, 0, 0, |
730 |
int8_t ccb[16] = { ATAPI_READ_SUBCHANNEL, 0, 0x40, 1, 0, 0, 0, |
| 732 |
sizeof(cdp->subchan)>>8, sizeof(cdp->subchan), |
731 |
sizeof(cdp->subchan)>>8, sizeof(cdp->subchan), |
| 733 |
0, 0, 0, 0, 0, 0, 0 }; |
732 |
0, 0, 0, 0, 0, 0, 0 }; |
| 734 |
|
733 |
|
| 735 |
if (len > sizeof(data) || |
734 |
if (len > sizeof(struct cd_sub_channel_info) || |
| 736 |
len < sizeof(struct cd_sub_channel_header)) { |
735 |
len < sizeof(struct cd_sub_channel_header)) { |
| 737 |
error = EINVAL; |
736 |
error = EINVAL; |
| 738 |
break; |
737 |
break; |
| 739 |
} |
738 |
} |
| 740 |
|
739 |
|
|
|
740 |
format=args->data_format; |
| 741 |
if ((format != CD_CURRENT_POSITION) && |
| 742 |
(format != CD_MEDIA_CATALOG) && (format != CD_TRACK_INFO)) { |
| 743 |
error = EINVAL; |
| 744 |
break; |
| 745 |
} |
| 746 |
|
| 747 |
ccb[1] = args->address_format & CD_MSF_FORMAT; |
| 748 |
|
| 741 |
if ((error = atapi_queue_cmd(cdp->atp, ccb, (caddr_t)&cdp->subchan, |
749 |
if ((error = atapi_queue_cmd(cdp->atp, ccb, (caddr_t)&cdp->subchan, |
| 742 |
sizeof(cdp->subchan), ATPR_F_READ, 10, |
750 |
sizeof(cdp->subchan), ATPR_F_READ, 10, |
| 743 |
NULL, NULL))) { |
751 |
NULL, NULL))) { |
| 744 |
break; |
752 |
break; |
| 745 |
} |
753 |
} |
| 746 |
abslba = cdp->subchan.abslba; |
754 |
|
| 747 |
rellba = cdp->subchan.rellba; |
755 |
/* |
| 748 |
if (args->address_format == CD_MSF_FORMAT) { |
756 |
* Ask for media catalogue or track info only if no audio play |
| 749 |
lba2msf(ntohl(abslba), |
757 |
* operation is in progress or the drive will return an error. |
| 750 |
&data.what.position.absaddr.msf.minute, |
758 |
*/ |
| 751 |
&data.what.position.absaddr.msf.second, |
759 |
|
| 752 |
&data.what.position.absaddr.msf.frame); |
760 |
if ((format == CD_MEDIA_CATALOG) || (format == CD_TRACK_INFO)) { |
| 753 |
lba2msf(ntohl(rellba), |
761 |
if (cdp->subchan.header.audio_status == 0x11) { |
| 754 |
&data.what.position.reladdr.msf.minute, |
762 |
error = EINVAL; |
| 755 |
&data.what.position.reladdr.msf.second, |
763 |
break; |
| 756 |
&data.what.position.reladdr.msf.frame); |
764 |
} |
| 757 |
} else { |
765 |
|
| 758 |
data.what.position.absaddr.lba = abslba; |
766 |
ccb[3] = format; |
| 759 |
data.what.position.reladdr.lba = rellba; |
767 |
if (format == CD_TRACK_INFO) |
|
|
768 |
ccb[6] = args->track; |
| 769 |
|
| 770 |
if ((error = atapi_queue_cmd(cdp->atp, ccb, |
| 771 |
(caddr_t)&cdp->subchan, |
| 772 |
sizeof(cdp->subchan), ATPR_F_READ, |
| 773 |
10, NULL, NULL))) { |
| 774 |
break; |
| 775 |
} |
| 760 |
} |
776 |
} |
| 761 |
data.header.audio_status = cdp->subchan.audio_status; |
777 |
|
| 762 |
data.what.position.control = cdp->subchan.control & 0xf; |
778 |
error = copyout(&cdp->subchan, args->data, len); |
| 763 |
data.what.position.addr_type = cdp->subchan.control >> 4; |
|
|
| 764 |
data.what.position.track_number = cdp->subchan.track; |
| 765 |
data.what.position.index_number = cdp->subchan.indx; |
| 766 |
error = copyout(&data, args->data, len); |
| 767 |
break; |
779 |
break; |
| 768 |
} |
780 |
} |
| 769 |
|
781 |
|