📄 aztcd.c
字号:
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; } if (qInfo.pointIndex==0xA1) /*Number of LastTrack*/ { DiskInfo.last = qInfo.diskTime.min; DiskInfo.last = azt_bcd2bin(DiskInfo.last); test=test|0x02; } if (qInfo.pointIndex==0xA2) /*DiskLength*/ { DiskInfo.diskLength.min=qInfo.diskTime.min; DiskInfo.diskLength.sec=qInfo.diskTime.sec; DiskInfo.diskLength.frame=qInfo.diskTime.frame; test=test|0x04; } if ((qInfo.pointIndex==DiskInfo.first)&&(test&0x01)) /*StartTime of First Track*/ { DiskInfo.firstTrack.min=qInfo.diskTime.min; DiskInfo.firstTrack.sec=qInfo.diskTime.sec; DiskInfo.firstTrack.frame=qInfo.diskTime.frame; test=test|0x08; } if (test==0x0F) break; }#ifdef AZT_DEBUG printk ("aztcd: exiting aztGetDiskInfo Time:%li\n",jiffies); printk("Disk Info: first %d last %d length %02X:%02X.%02X dez first %02X:%02X.%02X dez\n", DiskInfo.first, DiskInfo.last, DiskInfo.diskLength.min, DiskInfo.diskLength.sec, DiskInfo.diskLength.frame, DiskInfo.firstTrack.min, DiskInfo.firstTrack.sec, DiskInfo.firstTrack.frame);#endif if (test!=0x0F) return -1; return 0;}#if AZT_MULTISESSION/* * Get Multisession Disk Info */static int aztGetMultiDiskInfo(void){ int limit, k=5; unsigned char test; struct azt_Toc qInfo;#ifdef AZT_DEBUG printk("aztcd: starting aztGetMultiDiskInfo\n");#endif do { azt_Play.start.min = Toc[DiskInfo.last+1].diskTime.min; azt_Play.start.sec = Toc[DiskInfo.last+1].diskTime.sec; azt_Play.start.frame = Toc[DiskInfo.last+1].diskTime.frame; test=0; for (limit=30;limit>0;limit--) /*Seek for LeadIn of next session*/ { if (aztSeek(&azt_Play)) RETURNM("aztGetMultiDiskInfo 1",-1); if (aztGetQChannelInfo(&qInfo)<0) RETURNM("aztGetMultiDiskInfo 2",-1); if ((qInfo.track==0)&&(qInfo.pointIndex)) break; /*LeadIn found*/ if ((azt_Play.start.sec+=10) > 59) { azt_Play.start.sec=0; azt_Play.start.min++; } } if (!limit) break; /*Check, if a leadin track was found, if not we're at the end of the disk*/#ifdef AZT_DEBUG_MULTISESSION printk("leadin found track %d pointIndex %x limit %d\n",qInfo.track,qInfo.pointIndex,limit);#endif for (limit=300;limit>0;limit--) { if (++azt_Play.start.frame>74) { azt_Play.start.frame=0; if (azt_Play.start.sec > 59) { azt_Play.start.sec=0; azt_Play.start.min++; } } if (aztSeek(&azt_Play)) RETURNM("aztGetMultiDiskInfo 3",-1); if (aztGetQChannelInfo(&qInfo)<0) RETURNM("aztGetMultiDiskInfo 4",-1); if (qInfo.pointIndex==0xA0) /*Number of NextTrack*/ { DiskInfo.next = qInfo.diskTime.min; DiskInfo.next = azt_bcd2bin(DiskInfo.next); test=test|0x01; } if (qInfo.pointIndex==0xA1) /*Number of LastTrack*/ { DiskInfo.last = qInfo.diskTime.min; DiskInfo.last = azt_bcd2bin(DiskInfo.last); test=test|0x02; } if (qInfo.pointIndex==0xA2) /*DiskLength*/ { DiskInfo.diskLength.min =qInfo.diskTime.min; DiskInfo.diskLength.sec =qInfo.diskTime.sec; DiskInfo.diskLength.frame=qInfo.diskTime.frame; test=test|0x04; } if ((qInfo.pointIndex==DiskInfo.next)&&(test&0x01)) /*StartTime of Next Track*/ { DiskInfo.nextSession.min=qInfo.diskTime.min; DiskInfo.nextSession.sec=qInfo.diskTime.sec; DiskInfo.nextSession.frame=qInfo.diskTime.frame; test=test|0x08; } if (test==0x0F) break; }#ifdef AZT_DEBUG_MULTISESSION printk ("MultiDisk Info: first %d next %d last %d length %02x:%02x.%02x dez first %02x:%02x.%02x dez next %02x:%02x.%02x dez\n", DiskInfo.first, DiskInfo.next, DiskInfo.last, DiskInfo.diskLength.min, DiskInfo.diskLength.sec, DiskInfo.diskLength.frame, DiskInfo.firstTrack.min, DiskInfo.firstTrack.sec, DiskInfo.firstTrack.frame, DiskInfo.nextSession.min, DiskInfo.nextSession.sec, DiskInfo.nextSession.frame);#endif if (test!=0x0F) break; else DiskInfo.multi=1; /*found TOC of more than one session*/ aztGetToc(1); } while(--k);#ifdef AZT_DEBUG printk ("aztcd: exiting aztGetMultiDiskInfo Time:%li\n",jiffies);#endif return 0;}#endif/* * Read the table of contents (TOC) */static int aztGetToc(int multi){ int i, px; int limit; struct azt_Toc qInfo;#ifdef AZT_DEBUG printk("aztcd: starting aztGetToc Time:%li\n",jiffies);#endif if (!multi) { for (i = 0; i < MAX_TRACKS; i++) Toc[i].pointIndex = 0; i = DiskInfo.last + 3; } else { for (i = DiskInfo.next; i < MAX_TRACKS; i++) Toc[i].pointIndex = 0; i = DiskInfo.last + 4 - DiskInfo.next; }/*Is there a good reason to stop motor before TOC read? if (aztSendCmd(ACMD_STOP)) RETURNM("aztGetToc 1",-1); STEN_LOW_WAIT;*/ if (!multi) { azt_mode = 0x05; if (aztSendCmd(ACMD_SEEK_TO_LEADIN)) RETURNM("aztGetToc 2",-1); STEN_LOW_WAIT; } for (limit = 300; limit > 0; limit--) { if (multi) { if (++azt_Play.start.sec > 59) { azt_Play.start.sec=0; azt_Play.start.min++; } if (aztSeek(&azt_Play)) RETURNM("aztGetToc 3",-1); } if (aztGetQChannelInfo(&qInfo) < 0) break; px = azt_bcd2bin(qInfo.pointIndex); if (px > 0 && px < MAX_TRACKS && qInfo.track == 0) if (Toc[px].pointIndex == 0) { Toc[px] = qInfo; i--; } if (i <= 0) break; } Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength; Toc[DiskInfo.last].trackTime = DiskInfo.diskLength;#ifdef AZT_DEBUG_MULTISESSION printk("aztcd: exiting aztGetToc\n"); for (i = 1; i <= DiskInfo.last+1; i++) printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez %02X:%02X.%02X dez\n", i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex, Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame, Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame); for (i = 100; i < 103; i++) printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez %02X:%02X.%02X dez\n", i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex, Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame, Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);#endif return limit > 0 ? 0 : -1;}/*########################################################################## Kernel Interface Functions ##########################################################################*/#ifdef AZT_KERNEL_PRIOR_2_1void aztcd_setup(char *str, int *ints)#else__initfunc(void aztcd_setup(char *str, int *ints))#endif{ if (ints[0] > 0) azt_port = ints[1]; if (ints[0] > 1) azt_cont = ints[2];}/* * Checking if the media has been changed*/static int check_aztcd_media_change(kdev_t full_dev){ if (aztDiskChanged) /* disk changed */ { aztDiskChanged=0; return 1; } else return 0; /* no change */}/* * Kernel IO-controls*/static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg){ int i, st; struct azt_Toc qInfo; struct cdrom_ti ti; struct cdrom_tochdr tocHdr; struct cdrom_msf msf; struct cdrom_tocentry entry; struct azt_Toc *tocPtr; struct cdrom_subchnl subchnl; struct cdrom_volctrl volctrl;#ifdef AZT_DEBUG printk("aztcd: starting aztcd_ioctl - Command:%x Time: %li\n",cmd, jiffies); printk("aztcd Status %x\n", getAztStatus());#endif if (!ip) RETURNM("aztcd_ioctl 1",-EINVAL); if (getAztStatus()<0) RETURNM("aztcd_ioctl 2", -EIO); if ((!aztTocUpToDate)||(aztDiskChanged)) { if ((i=aztUpdateToc())<0) RETURNM("aztcd_ioctl 3", i); /* error reading TOC */ } switch (cmd) { case CDROMSTART: /* Spin up the drive. Don't know, what to do, at least close the tray */#if AZT_PRIVATE_IOCTLS if (aztSendCmd(ACMD_CLOSE)) RETURNM("aztcd_ioctl 4",-1); STEN_LOW_WAIT;#endif break; case CDROMSTOP: /* Spin down the drive */ if (aztSendCmd(ACMD_STOP)) RETURNM("aztcd_ioctl 5",-1); STEN_LOW_WAIT; /* should we do anything if it fails? */ aztAudioStatus = CDROM_AUDIO_NO_STATUS; break; case CDROMPAUSE: /* Pause the drive */ if (aztAudioStatus != CDROM_AUDIO_PLAY) return -EINVAL; if (aztGetQChannelInfo(&qInfo) < 0) { /* didn't get q channel info */ aztAudioStatus = CDROM_AUDIO_NO_STATUS; RETURNM("aztcd_ioctl 7",0); } azt_Play.start = qInfo.diskTime; /* remember restart point */ if (aztSendCmd(ACMD_PAUSE)) RETURNM("aztcd_ioctl 8",-1); STEN_LOW_WAIT; aztAudioStatus = CDROM_AUDIO_PAUSED; break; case CDROMRESUME: /* Play it again, Sam */ if (aztAudioStatus != CDROM_AUDIO_PAUSED) return -EINVAL; /* restart the drive at the saved position. */ i = aztPlay(&azt_Play); if (i < 0) { aztAudioStatus = CDROM_AUDIO_ERROR; return -EIO; } aztAudioStatus = CDROM_AUDIO_PLAY; break; case CDROMMULTISESSION: /*multisession support -- experimental*/ { struct cdrom_multisession ms;#ifdef AZT_DEBUG printk("aztcd ioctl MULTISESSION\n");#endif st = verify_area(VERIFY_WRITE, (void*) arg, sizeof(struct cdrom_multisession)); if (st) return st; memcpy_fromfs(&ms, (void*) arg, sizeof(struct cdrom_multisession)); if (ms.addr_format == CDROM_MSF) { ms.addr.msf.minute = azt_bcd2bin(DiskInfo.lastSession.min); ms.addr.msf.second = azt_bcd2bin(DiskInfo.lastSession.sec); ms.addr.msf.frame = azt_bcd2bin(DiskInfo.lastSession.frame); } else if (ms.addr_format == CDROM_LBA) ms.addr.lba = azt_msf2hsg(&DiskInfo.lastSession); else return -EINVAL; ms.xa_flag = DiskInfo.xa; memcpy_tofs((void*) arg, &ms, sizeof(struct cdrom_multisession));#ifdef AZT_DEBUG if (ms.addr_format == CDROM_MSF) printk("aztcd multisession xa:%d, msf:%02x:%02x.%02x [%02x:%02x.%02x])\n", ms.xa_flag, ms.addr.msf.minute, ms.addr.msf.second, ms.addr.msf.frame, DiskInfo.lastSession.min, DiskInfo.lastSession.sec, DiskInfo.lastSession.frame); else printk("aztcd multisession %d, lba:0x%08x [%02x:%02x.%02x])\n", ms.xa_flag, ms.addr.lba, DiskInfo.lastSession.min,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -