⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aztcd.c

📁 cdrom device drive for linux.
💻 C
📖 第 1 页 / 共 5 页
字号:
			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 + -