📄 aztcd.c
字号:
}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(¬Used)) 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(¬Used) < 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 = Toc[DiskInfo.first].diskTime.min; DiskInfo.lastSession.sec = Toc[DiskInfo.first].diskTime.sec; DiskInfo.lastSession.frame = Toc[DiskInfo.first].diskTime.frame; } aztTocUpToDate = 1;#ifdef AZT_DEBUG printk("aztcd: exiting aztUpdateToc Time:%li\n", jiffies);#endif return 0;}/* Read the table of contents header, i.e. no. of tracks and start of first * track */static int aztGetDiskInfo(){ int limit; unsigned char test; struct azt_Toc qInfo;#ifdef AZT_DEBUG printk("aztcd: starting aztGetDiskInfo Time:%li\n", jiffies);#endif if (aztSendCmd(ACMD_SEEK_TO_LEADIN)) RETURNM("aztGetDiskInfo 1", -1); STEN_LOW_WAIT; test = 0; for (limit = 300; limit > 0; limit--) { if (aztGetQChannelInfo(&qInfo) < 0) RETURNM("aztGetDiskInfo 2", -1); if (qInfo.pointIndex == 0xA0) { /*Number of FirstTrack */ DiskInfo.first = qInfo.diskTime.min; DiskInfo.first = azt_bcd2bin(DiskInfo.first); test = test | 0x01;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -