📄 aztcd.c
字号:
return -EIO;
}
aztAudioStatus = CDROM_AUDIO_PLAY;
break;
case CDROMPLAYMSF: /* Play starting at the given MSF address. */
/* if (aztAudioStatus == CDROM_AUDIO_PLAY)
{ if (aztSendCmd(ACMD_STOP)) RETURNM("aztcd_ioctl 9",-1);
STEN_LOW;
aztAudioStatus = CDROM_AUDIO_NO_STATUS;
}
*/
if (copy_from_user(&msf, (void *) arg, sizeof msf))
return -EFAULT;
/* convert to bcd */
azt_bin2bcd(&msf.cdmsf_min0);
azt_bin2bcd(&msf.cdmsf_sec0);
azt_bin2bcd(&msf.cdmsf_frame0);
azt_bin2bcd(&msf.cdmsf_min1);
azt_bin2bcd(&msf.cdmsf_sec1);
azt_bin2bcd(&msf.cdmsf_frame1);
azt_Play.start.min = msf.cdmsf_min0;
azt_Play.start.sec = msf.cdmsf_sec0;
azt_Play.start.frame = msf.cdmsf_frame0;
azt_Play.end.min = msf.cdmsf_min1;
azt_Play.end.sec = msf.cdmsf_sec1;
azt_Play.end.frame = msf.cdmsf_frame1;
#ifdef AZT_DEBUG
printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n",
azt_Play.start.min, azt_Play.start.sec,
azt_Play.start.frame, azt_Play.end.min,
azt_Play.end.sec, azt_Play.end.frame);
#endif
i = aztPlay(&azt_Play);
if (i < 0) {
aztAudioStatus = CDROM_AUDIO_ERROR;
return -EIO;
}
aztAudioStatus = CDROM_AUDIO_PLAY;
break;
case CDROMREADTOCHDR: /* Read the table of contents header */
tocHdr.cdth_trk0 = DiskInfo.first;
tocHdr.cdth_trk1 = DiskInfo.last;
if (copy_to_user((void *) arg, &tocHdr, sizeof tocHdr))
return -EFAULT;
break;
case CDROMREADTOCENTRY: /* Read an entry in the table of contents */
if (copy_from_user(&entry, (void *) arg, sizeof entry))
return -EFAULT;
if ((!aztTocUpToDate) || aztDiskChanged)
aztUpdateToc();
if (entry.cdte_track == CDROM_LEADOUT)
tocPtr = &Toc[DiskInfo.last + 1];
else if (entry.cdte_track > DiskInfo.last
|| entry.cdte_track < DiskInfo.first) {
return -EINVAL;
} else
tocPtr = &Toc[entry.cdte_track];
entry.cdte_adr = tocPtr->ctrl_addr;
entry.cdte_ctrl = tocPtr->ctrl_addr >> 4;
if (entry.cdte_format == CDROM_LBA)
entry.cdte_addr.lba =
azt_msf2hsg(&tocPtr->diskTime);
else if (entry.cdte_format == CDROM_MSF) {
entry.cdte_addr.msf.minute =
azt_bcd2bin(tocPtr->diskTime.min);
entry.cdte_addr.msf.second =
azt_bcd2bin(tocPtr->diskTime.sec);
entry.cdte_addr.msf.frame =
azt_bcd2bin(tocPtr->diskTime.frame);
} else {
return -EINVAL;
}
if (copy_to_user((void *) arg, &entry, sizeof entry))
return -EFAULT;
break;
case CDROMSUBCHNL: /* Get subchannel info */
if (copy_from_user
(&subchnl, (void *) arg, sizeof(struct cdrom_subchnl)))
return -EFAULT;
if (aztGetQChannelInfo(&qInfo) < 0) {
#ifdef AZT_DEBUG
printk
("aztcd: exiting aztcd_ioctl - Error 3 - Command:%x\n",
cmd);
#endif
return -EIO;
}
subchnl.cdsc_audiostatus = aztAudioStatus;
subchnl.cdsc_adr = qInfo.ctrl_addr;
subchnl.cdsc_ctrl = qInfo.ctrl_addr >> 4;
subchnl.cdsc_trk = azt_bcd2bin(qInfo.track);
subchnl.cdsc_ind = azt_bcd2bin(qInfo.pointIndex);
if (subchnl.cdsc_format == CDROM_LBA) {
subchnl.cdsc_absaddr.lba =
azt_msf2hsg(&qInfo.diskTime);
subchnl.cdsc_reladdr.lba =
azt_msf2hsg(&qInfo.trackTime);
} else { /*default */
subchnl.cdsc_format = CDROM_MSF;
subchnl.cdsc_absaddr.msf.minute =
azt_bcd2bin(qInfo.diskTime.min);
subchnl.cdsc_absaddr.msf.second =
azt_bcd2bin(qInfo.diskTime.sec);
subchnl.cdsc_absaddr.msf.frame =
azt_bcd2bin(qInfo.diskTime.frame);
subchnl.cdsc_reladdr.msf.minute =
azt_bcd2bin(qInfo.trackTime.min);
subchnl.cdsc_reladdr.msf.second =
azt_bcd2bin(qInfo.trackTime.sec);
subchnl.cdsc_reladdr.msf.frame =
azt_bcd2bin(qInfo.trackTime.frame);
}
if (copy_to_user
((void *) arg, &subchnl, sizeof(struct cdrom_subchnl)))
return -EFAULT;
break;
case CDROMVOLCTRL: /* Volume control
* With my Aztech CD268-01A volume control does not work, I can only
turn the channels on (any value !=0) or off (value==0). Maybe it
works better with your drive */
if (copy_from_user
(&volctrl, (char *) arg, sizeof(volctrl)))
return -EFAULT;
azt_Play.start.min = 0x21;
azt_Play.start.sec = 0x84;
azt_Play.start.frame = volctrl.channel0;
azt_Play.end.min = volctrl.channel1;
azt_Play.end.sec = volctrl.channel2;
azt_Play.end.frame = volctrl.channel3;
sendAztCmd(ACMD_SET_VOLUME, &azt_Play);
STEN_LOW_WAIT;
break;
case CDROMEJECT:
aztUnlockDoor(); /* Assume user knows what they're doing */
/* all drives can at least stop! */
if (aztAudioStatus == CDROM_AUDIO_PLAY) {
if (aztSendCmd(ACMD_STOP))
RETURNM("azt_ioctl 10", -1);
STEN_LOW_WAIT;
}
if (aztSendCmd(ACMD_EJECT))
RETURNM("azt_ioctl 11", -1);
STEN_LOW_WAIT;
aztAudioStatus = CDROM_AUDIO_NO_STATUS;
break;
case CDROMEJECT_SW:
azt_auto_eject = (char) arg;
break;
case CDROMRESET:
outb(ACMD_SOFT_RESET, CMD_PORT); /*send reset */
STEN_LOW;
if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? */
printk
("aztcd: AZTECH CD-ROM drive does not respond\n");
}
break;
/*Take care, the following code is not compatible with other CD-ROM drivers,
use it at your own risk with cdplay.c. Set AZT_PRIVATE_IOCTLS to 0 in aztcd.h,
if you do not want to use it!
*/
#if AZT_PRIVATE_IOCTLS
case CDROMREADCOOKED: /*read data in mode 1 (2048 Bytes) */
case CDROMREADRAW: /*read data in mode 2 (2336 Bytes) */
{
if (copy_from_user(&msf, (void *) arg, sizeof msf))
return -EFAULT;
/* convert to bcd */
azt_bin2bcd(&msf.cdmsf_min0);
azt_bin2bcd(&msf.cdmsf_sec0);
azt_bin2bcd(&msf.cdmsf_frame0);
msf.cdmsf_min1 = 0;
msf.cdmsf_sec1 = 0;
msf.cdmsf_frame1 = 1; /*read only one frame */
azt_Play.start.min = msf.cdmsf_min0;
azt_Play.start.sec = msf.cdmsf_sec0;
azt_Play.start.frame = msf.cdmsf_frame0;
azt_Play.end.min = msf.cdmsf_min1;
azt_Play.end.sec = msf.cdmsf_sec1;
azt_Play.end.frame = msf.cdmsf_frame1;
if (cmd == CDROMREADRAW) {
if (DiskInfo.xa) {
return -1; /*XA Disks can't be read raw */
} else {
if (sendAztCmd
(ACMD_PLAY_READ_RAW,
&azt_Play))
return -1;
DTEN_LOW;
insb(DATA_PORT, buf,
CD_FRAMESIZE_RAW);
if (copy_to_user
((void *) arg, &buf,
CD_FRAMESIZE_RAW))
return -EFAULT;
}
} else
/*CDROMREADCOOKED*/ {
if (sendAztCmd(ACMD_PLAY_READ, &azt_Play))
return -1;
DTEN_LOW;
insb(DATA_PORT, buf, CD_FRAMESIZE);
if (copy_to_user
((void *) arg, &buf, CD_FRAMESIZE))
return -EFAULT;
}
}
break;
case CDROMSEEK: /*seek msf address */
if (copy_from_user(&msf, (void *) arg, sizeof msf))
return -EFAULT;
/* convert to bcd */
azt_bin2bcd(&msf.cdmsf_min0);
azt_bin2bcd(&msf.cdmsf_sec0);
azt_bin2bcd(&msf.cdmsf_frame0);
azt_Play.start.min = msf.cdmsf_min0;
azt_Play.start.sec = msf.cdmsf_sec0;
azt_Play.start.frame = msf.cdmsf_frame0;
if (aztSeek(&azt_Play))
return -1;
break;
#endif /*end of incompatible code */
case CDROMREADMODE1: /*set read data in mode 1 */
return aztSetDiskType(AZT_MODE_1);
case CDROMREADMODE2: /*set read data in mode 2 */
return aztSetDiskType(AZT_MODE_2);
default:
return -EINVAL;
}
#ifdef AZT_DEBUG
printk("aztcd: exiting aztcd_ioctl Command:%x Time:%li\n", cmd,
jiffies);
#endif
return 0;
}
/*
* Take care of the different block sizes between cdrom and Linux.
* When Linux gets variable block sizes this will probably go away.
*/
static void azt_transfer(void)
{
#ifdef AZT_TEST
printk("aztcd: executing azt_transfer Time:%li\n", jiffies);
#endif
if (CURRENT_VALID) {
while (CURRENT->nr_sectors) {
int bn = CURRENT->sector / 4;
int i;
for (i = 0; i < AZT_BUF_SIZ && azt_buf_bn[i] != bn;
++i);
if (i < AZT_BUF_SIZ) {
int offs =
(i * 4 + (CURRENT->sector & 3)) * 512;
int nr_sectors = 4 - (CURRENT->sector & 3);
if (azt_buf_out != i) {
azt_buf_out = i;
if (azt_buf_bn[i] != bn) {
azt_buf_out = -1;
continue;
}
}
if (nr_sectors > CURRENT->nr_sectors)
nr_sectors = CURRENT->nr_sectors;
memcpy(CURRENT->buffer, azt_buf + offs,
nr_sectors * 512);
CURRENT->nr_sectors -= nr_sectors;
CURRENT->sector += nr_sectors;
CURRENT->buffer += nr_sectors * 512;
} else {
azt_buf_out = -1;
break;
}
}
}
}
static void do_aztcd_request(request_queue_t * q)
{
#ifdef AZT_TEST
printk(" do_aztcd_request(%ld+%ld) Time:%li\n", CURRENT->sector,
CURRENT->nr_sectors, jiffies);
#endif
if (DiskInfo.audio) {
printk("aztcd: Error, tried to mount an Audio CD\n");
end_request(0);
return;
}
azt_transfer_is_active = 1;
while (CURRENT_VALID) {
if (CURRENT->bh) {
if (!buffer_locked(CURRENT->bh))
panic(DEVICE_NAME ": block not locked");
}
azt_transfer();
if (CURRENT->nr_sectors == 0) {
end_request(1);
} else {
azt_buf_out = -1; /* Want to read a block not in buffer */
if (azt_state == AZT_S_IDLE) {
if ((!aztTocUpToDate) || aztDiskChanged) {
if (aztUpdateToc() < 0) {
while (CURRENT_VALID)
end_request(0);
break;
}
}
azt_state = AZT_S_START;
AztTries = 5;
SET_TIMER(azt_poll, HZ / 100);
}
break;
}
}
azt_transfer_is_active = 0;
#ifdef AZT_TEST2
printk
("azt_next_bn:%x azt_buf_in:%x azt_buf_out:%x azt_buf_bn:%x\n",
azt_next_bn, azt_buf_in, azt_buf_out, azt_buf_bn[azt_buf_in]);
printk(" do_aztcd_request ends Time:%li\n", jiffies);
#endif
}
static void azt_invalidate_buffers(void)
{
int i;
#ifdef AZT_DEBUG
printk("aztcd: executing azt_invalidate_buffers\n");
#endif
for (i = 0; i < AZT_BUF_SIZ; ++i)
azt_buf_bn[i] = -1;
azt_buf_out = -1;
}
/*
* Open the device special file. Check that a disk is in.
*/
int aztcd_open(struct inode *ip, struct file *fp)
{
int st;
#ifdef AZT_DEBUG
printk("aztcd: starting aztcd_open\n");
#endif
if (aztPresent == 0)
return -ENXIO; /* no hardware */
if (!azt_open_count && azt_state == AZT_S_IDLE) {
azt_invalidate_buffers();
st = getAztStatus(); /* check drive status */
if (st == -1)
goto err_out; /* drive doesn't respond */
if (st & AST_DOOR_OPEN) { /* close door, then get the status again. */
printk("aztcd: Door Open?\n");
aztCloseDoor();
st = getAztStatus();
}
if ((st & AST_NOT_READY) || (st & AST_DSK_CHG)) { /*no disk in drive or changed */
printk
("aztcd: Disk Changed or No Disk in Drive?\n");
aztTocUpToDate = 0;
}
if (aztUpdateToc())
goto err_out;
}
++azt_open_count;
aztLockDoor();
#ifdef AZT_DEBUG
printk("aztcd: exiting aztcd_open\n");
#endif
return 0;
err_out:
return -EIO;
}
/*
* On close, we flush all azt blocks from the buffer cache.
*/
static int aztcd_release(struct inode *inode, struct file *file)
{
#ifdef AZT_DEBUG
printk("aztcd: executing aztcd_release\n");
printk("inode: %p, inode->i_rdev: %x file: %p\n", inode,
inode->i_rdev, file);
#endif
if (!--azt_open_count) {
azt_invalidate_buffers();
aztUnlockDoor();
if (azt_auto_eject)
aztSendCmd(ACMD_EJECT);
CLEAR_TIMER;
}
return 0;
}
/*
* Test for presence of drive and initialize it. Called at boot time.
*/
int __init aztcd_init(void)
{
long int count, max_count;
unsigned char result[50];
int st;
int i = 0;
if (azt_port == 0) {
printk("aztcd: no Aztech CD-ROM Initialization");
return -EIO;
}
printk
("aztcd: AZTECH, ORCHID, OKANO, WEARNES, TXC, CyDROM CD-ROM Driver\n");
printk("aztcd: (C) 1994-98 W.Zimmermann\n");
if (azt_port == -1) {
printk
("aztcd: KernelVersion=%s DriverVersion=%s For IDE/ATAPI-drives use ide-cd.c\n",
UTS_RELEASE, AZT_VERSION);
} else
printk
("aztcd: DriverVersion=%s BaseAddress=0x%x For IDE/ATAPI-drives use ide-cd.c\n",
AZT_VERSION, azt_port);
printk
("aztcd: If you have problems, read /usr/src/linux/Documentation/cdrom/aztcd\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -