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

📄 aztcd.c

📁 cdrom device drive for linux.
💻 C
📖 第 1 页 / 共 5 页
字号:
			break;
		}
	} while (aztIndatum & AFL_DATA);
}

/* 
 * Macro for timer wait on STEN=Low, should only be used for 'slow' commands;
 * may cause kernel panic when used in the wrong place
*/
#define STEN_LOW_WAIT   statusAzt()
void statusAzt(void)
{
	AztTimeout = AZT_STATUS_DELAY;
	SET_TIMER(aztStatTimer, HZ / 100);
	sleep_on(&azt_waitq);
	if (AztTimeout <= 0)
		printk("aztcd: Error Wait STEN_LOW_WAIT command:%x\n",
		       aztCmd);
	return;
}

static void aztStatTimer(void)
{
	if (!(inb(STATUS_PORT) & AFL_STATUS)) {
		wake_up(&azt_waitq);
		return;
	}
	AztTimeout--;
	if (AztTimeout <= 0) {
		wake_up(&azt_waitq);
		printk("aztcd: Error aztStatTimer: Timeout\n");
		return;
	}
	SET_TIMER(aztStatTimer, HZ / 100);
}

/*##########################################################################
  CDROM Drive Command Functions
  ##########################################################################
*/
/* 
 * Send a single command, return -1 on error, else 0
*/
static int aztSendCmd(int cmd)
{
	unsigned char data;
	int retry;

#ifdef AZT_DEBUG
	printk("aztcd: Executing command %x\n", cmd);
#endif

	if ((azt_port == 0x1f0) || (azt_port == 0x170))
		SWITCH_IDE_SLAVE;	/*switch IDE interface to slave configuration */

	aztCmd = cmd;
	outb(POLLED, MODE_PORT);
	do {
		if (inb(STATUS_PORT) & AFL_STATUS)
			break;
		inb(DATA_PORT);	/* if status left from last command, read and */
	} while (1);		/* discard it */
	do {
		if (inb(STATUS_PORT) & AFL_DATA)
			break;
		inb(DATA_PORT);	/* if data left from last command, read and */
	} while (1);		/* discard it */
	for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
		outb((unsigned char) cmd, CMD_PORT);
		STEN_LOW;
		data = inb(DATA_PORT);
		if (data == AFL_OP_OK) {
			return 0;
		}		/*OP_OK? */
		if (data == AFL_OP_ERR) {
			STEN_LOW;
			data = inb(DATA_PORT);
			printk
			    ("### Error 1 aztcd: aztSendCmd %x  Error Code %x\n",
			     cmd, data);
		}
	}
	if (retry >= AZT_RETRY_ATTEMPTS) {
		printk("### Error 2 aztcd: aztSendCmd %x \n", cmd);
		azt_error = 0xA5;
	}
	RETURNM("aztSendCmd", -1);
}

/*
 * Send a play or read command to the drive, return -1 on error, else 0
*/
static int sendAztCmd(int cmd, struct azt_Play_msf *params)
{
	unsigned char data;
	int retry;

#ifdef AZT_DEBUG
	printk("aztcd: play start=%02x:%02x:%02x  end=%02x:%02x:%02x\n",
	       params->start.min, params->start.sec, params->start.frame,
	       params->end.min, params->end.sec, params->end.frame);
#endif
	for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
		aztSendCmd(cmd);
		outb(params->start.min, CMD_PORT);
		outb(params->start.sec, CMD_PORT);
		outb(params->start.frame, CMD_PORT);
		outb(params->end.min, CMD_PORT);
		outb(params->end.sec, CMD_PORT);
		outb(params->end.frame, CMD_PORT);
		STEN_LOW;
		data = inb(DATA_PORT);
		if (data == AFL_PA_OK) {
			return 0;
		}		/*PA_OK ? */
		if (data == AFL_PA_ERR) {
			STEN_LOW;
			data = inb(DATA_PORT);
			printk
			    ("### Error 1 aztcd: sendAztCmd %x  Error Code %x\n",
			     cmd, data);
		}
	}
	if (retry >= AZT_RETRY_ATTEMPTS) {
		printk("### Error 2 aztcd: sendAztCmd %x\n ", cmd);
		azt_error = 0xA5;
	}
	RETURNM("sendAztCmd", -1);
}

/*
 * Send a seek command to the drive, return -1 on error, else 0
*/
static int aztSeek(struct azt_Play_msf *params)
{
	unsigned char data;
	int retry;

#ifdef AZT_DEBUG
	printk("aztcd: aztSeek %02x:%02x:%02x\n",
	       params->start.min, params->start.sec, params->start.frame);
#endif
	for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
		aztSendCmd(ACMD_SEEK);
		outb(params->start.min, CMD_PORT);
		outb(params->start.sec, CMD_PORT);
		outb(params->start.frame, CMD_PORT);
		STEN_LOW;
		data = inb(DATA_PORT);
		if (data == AFL_PA_OK) {
			return 0;
		}		/*PA_OK ? */
		if (data == AFL_PA_ERR) {
			STEN_LOW;
			data = inb(DATA_PORT);
			printk("### Error 1 aztcd: aztSeek\n");
		}
	}
	if (retry >= AZT_RETRY_ATTEMPTS) {
		printk("### Error 2 aztcd: aztSeek\n ");
		azt_error = 0xA5;
	}
	RETURNM("aztSeek", -1);
}

/* Send a Set Disk Type command
   does not seem to work with Aztech drives, behavior is completely indepen-
   dent on which mode is set ???
*/
static int aztSetDiskType(int type)
{
	unsigned char data;
	int retry;

#ifdef AZT_DEBUG
	printk("aztcd: set disk type command: type= %i\n", type);
#endif
	for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
		aztSendCmd(ACMD_SET_DISK_TYPE);
		outb(type, CMD_PORT);
		STEN_LOW;
		data = inb(DATA_PORT);
		if (data == AFL_PA_OK) {	/*PA_OK ? */
			azt_read_mode = type;
			return 0;
		}
		if (data == AFL_PA_ERR) {
			STEN_LOW;
			data = inb(DATA_PORT);
			printk
			    ("### Error 1 aztcd: aztSetDiskType %x Error Code %x\n",
			     type, data);
		}
	}
	if (retry >= AZT_RETRY_ATTEMPTS) {
		printk("### Error 2 aztcd: aztSetDiskType %x\n ", type);
		azt_error = 0xA5;
	}
	RETURNM("aztSetDiskType", -1);
}


/* used in azt_poll to poll the status, expects another program to issue a 
 * ACMD_GET_STATUS directly before 
 */
static int aztStatus(void)
{
	int st;
/*	int i;

	i = inb(STATUS_PORT) & AFL_STATUS;    is STEN=0?    ???
	if (!i)
*/ STEN_LOW;
	if (aztTimeOutCount < AZT_TIMEOUT) {
		st = inb(DATA_PORT) & 0xFF;
		return st;
	} else
		RETURNM("aztStatus", -1);
}

/*
 * Get the drive status
 */
static int getAztStatus(void)
{
	int st;

	if (aztSendCmd(ACMD_GET_STATUS))
		RETURNM("getAztStatus 1", -1);
	STEN_LOW;
	st = inb(DATA_PORT) & 0xFF;
#ifdef AZT_DEBUG
	printk("aztcd: Status = %x\n", st);
#endif
	if ((st == 0xFF) || (st & AST_CMD_CHECK)) {
		printk
		    ("aztcd: AST_CMD_CHECK error or no status available\n");
		return -1;
	}

	if (((st & AST_MODE_BITS) != AST_BUSY)
	    && (aztAudioStatus == CDROM_AUDIO_PLAY))
		/* XXX might be an error? look at q-channel? */
		aztAudioStatus = CDROM_AUDIO_COMPLETED;

	if ((st & AST_DSK_CHG) || (st & AST_NOT_READY)) {
		aztDiskChanged = 1;
		aztTocUpToDate = 0;
		aztAudioStatus = CDROM_AUDIO_NO_STATUS;
	}
	return st;
}


/*
 * Send a 'Play' command and get the status.  Use only from the top half.
 */
static int aztPlay(struct azt_Play_msf *arg)
{
	if (sendAztCmd(ACMD_PLAY_AUDIO, arg) < 0)
		RETURNM("aztPlay", -1);
	return 0;
}

/*
 * Subroutines to automatically close the door (tray) and 
 * lock it closed when the cd is mounted.  Leave the tray
 * locking as an option
 */
static void aztCloseDoor(void)
{
	aztSendCmd(ACMD_CLOSE);
	STEN_LOW;
	return;
}

static void aztLockDoor(void)
{
#if AZT_ALLOW_TRAY_LOCK
	aztSendCmd(ACMD_LOCK);
	STEN_LOW;
#endif
	return;
}

static void aztUnlockDoor(void)
{
#if AZT_ALLOW_TRAY_LOCK
	aztSendCmd(ACMD_UNLOCK);
	STEN_LOW;
#endif
	return;
}

/*
 * Read a value from the drive.  Should return quickly, so a busy wait
 * is used to avoid excessive rescheduling. The read command itself must
 * be issued with aztSendCmd() directly before
 */
static int aztGetValue(unsigned char *result)
{
	int s;

	STEN_LOW;
	if (aztTimeOutCount >= AZT_TIMEOUT) {
		printk("aztcd: aztGetValue timeout\n");
		return -1;
	}
	s = inb(DATA_PORT) & 0xFF;
	*result = (unsigned char) s;
	return 0;
}

/*
 * Read the current Q-channel info.  Also used for reading the
 * table of contents.
 */
int aztGetQChannelInfo(struct azt_Toc *qp)
{
	unsigned char notUsed;
	int st;

#ifdef AZT_DEBUG
	printk("aztcd: starting aztGetQChannelInfo  Time:%li\n", jiffies);
#endif
	if ((st = getAztStatus()) == -1)
		RETURNM("aztGetQChannelInfo 1", -1);
	if (aztSendCmd(ACMD_GET_Q_CHANNEL))
		RETURNM("aztGetQChannelInfo 2", -1);
	/*STEN_LOW_WAIT; ??? Dosemu0.60's cdrom.c does not like STEN_LOW_WAIT here */
	if (aztGetValue(&notUsed))
		RETURNM("aztGetQChannelInfo 3", -1);	/*??? Nullbyte einlesen */
	if ((st & AST_MODE_BITS) == AST_INITIAL) {
		qp->ctrl_addr = 0;	/* when audio stop ACMD_GET_Q_CHANNEL returns */
		qp->track = 0;	/* only one byte with Aztech drives */
		qp->pointIndex = 0;
		qp->trackTime.min = 0;
		qp->trackTime.sec = 0;
		qp->trackTime.frame = 0;
		qp->diskTime.min = 0;
		qp->diskTime.sec = 0;
		qp->diskTime.frame = 0;
		return 0;
	} else {
		if (aztGetValue(&qp->ctrl_addr) < 0)
			RETURNM("aztGetQChannelInfo 4", -1);
		if (aztGetValue(&qp->track) < 0)
			RETURNM("aztGetQChannelInfo 4", -1);
		if (aztGetValue(&qp->pointIndex) < 0)
			RETURNM("aztGetQChannelInfo 4", -1);
		if (aztGetValue(&qp->trackTime.min) < 0)
			RETURNM("aztGetQChannelInfo 4", -1);
		if (aztGetValue(&qp->trackTime.sec) < 0)
			RETURNM("aztGetQChannelInfo 4", -1);
		if (aztGetValue(&qp->trackTime.frame) < 0)
			RETURNM("aztGetQChannelInfo 4", -1);
		if (aztGetValue(&notUsed) < 0)
			RETURNM("aztGetQChannelInfo 4", -1);
		if (aztGetValue(&qp->diskTime.min) < 0)
			RETURNM("aztGetQChannelInfo 4", -1);
		if (aztGetValue(&qp->diskTime.sec) < 0)
			RETURNM("aztGetQChannelInfo 4", -1);
		if (aztGetValue(&qp->diskTime.frame) < 0)
			RETURNM("aztGetQChannelInfo 4", -1);
	}
#ifdef AZT_DEBUG
	printk("aztcd: exiting aztGetQChannelInfo  Time:%li\n", jiffies);
#endif
	return 0;
}

/*
 * Read the table of contents (TOC) and TOC header if necessary
 */
static int aztUpdateToc()
{
	int st;

#ifdef AZT_DEBUG
	printk("aztcd: starting aztUpdateToc  Time:%li\n", jiffies);
#endif
	if (aztTocUpToDate)
		return 0;

	if (aztGetDiskInfo() < 0)
		return -EIO;

	if (aztGetToc(0) < 0)
		return -EIO;

	/*audio disk detection
	   with my Aztech drive there is no audio status bit, so I use the copy
	   protection bit of the first track. If this track is copy protected 
	   (copy bit = 0), I assume, it's an audio  disk. Strange, but works ??? */
	if (!(Toc[DiskInfo.first].ctrl_addr & 0x40))
		DiskInfo.audio = 1;
	else
		DiskInfo.audio = 0;

	/* XA detection */
	if (!DiskInfo.audio) {
		azt_Play.start.min = 0;	/*XA detection only seems to work */
		azt_Play.start.sec = 2;	/*when we play a track */
		azt_Play.start.frame = 0;
		azt_Play.end.min = 0;
		azt_Play.end.sec = 0;
		azt_Play.end.frame = 1;
		if (sendAztCmd(ACMD_PLAY_READ, &azt_Play))
			return -1;
		DTEN_LOW;
		for (st = 0; st < CD_FRAMESIZE; st++)
			inb(DATA_PORT);
	}
	DiskInfo.xa = getAztStatus() & AST_MODE;
	if (DiskInfo.xa) {
		printk
		    ("aztcd: XA support experimental - mail results to Werner.Zimmermann@fht-esslingen.de\n");
	}

	/*multisession detection
	   support for multisession CDs is done automatically with Aztech drives,
	   we don't have to take care about TOC redirection; if we want the isofs
	   to take care about redirection, we have to set AZT_MULTISESSION to 1 */
	DiskInfo.multi = 0;
#if AZT_MULTISESSION
	if (DiskInfo.xa) {
		aztGetMultiDiskInfo();	/*here Disk.Info.multi is set */
	}
#endif
	if (DiskInfo.multi) {
		DiskInfo.lastSession.min = Toc[DiskInfo.next].diskTime.min;
		DiskInfo.lastSession.sec = Toc[DiskInfo.next].diskTime.sec;
		DiskInfo.lastSession.frame =
		    Toc[DiskInfo.next].diskTime.frame;
		printk("aztcd: Multisession support experimental\n");
	} else {
		DiskInfo.lastSession.min =

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -