📄 aztcd.c
字号:
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");#ifdef AZT_SW32 /*CDROM connected to Soundwave32 card */ if ((0xFF00 & inw(AZT_SW32_ID_REG)) != 0x4500) { printk ("aztcd: no Soundwave32 card detected at base:%x init:%x config:%x id:%x\n", AZT_SW32_BASE_ADDR, AZT_SW32_INIT, AZT_SW32_CONFIG_REG, AZT_SW32_ID_REG); return -EIO; } else { printk(KERN_INFO "aztcd: Soundwave32 card detected at %x Version %x\n", AZT_SW32_BASE_ADDR, inw(AZT_SW32_ID_REG)); outw(AZT_SW32_INIT, AZT_SW32_CONFIG_REG); for (count = 0; count < 10000; count++); /*delay a bit */ }#endif /* check for presence of drive */ if (azt_port == -1) { /* autoprobing */ for (i = 0; (azt_port_auto[i] != 0) && (i < 16); i++) { azt_port = azt_port_auto[i]; printk("aztcd: Autoprobing BaseAddress=0x%x \n", azt_port); st = check_region(azt_port, 4); /*proprietary interfaces need 4 bytes */ if (st) continue; outb(POLLED, MODE_PORT); inb(CMD_PORT); inb(CMD_PORT); outb(ACMD_GET_VERSION, CMD_PORT); /*Try to get version info */ aztTimeOutCount = 0; do { aztIndatum = inb(STATUS_PORT); aztTimeOutCount++; if (aztTimeOutCount >= AZT_FAST_TIMEOUT) break; } while (aztIndatum & AFL_STATUS); if (inb(DATA_PORT) == AFL_OP_OK) break; } if ((azt_port_auto[i] == 0) || (i == 16)) { printk("aztcd: no AZTECH CD-ROM drive found\n"); return -EIO; } } else { /* no autoprobing */ if ((azt_port == 0x1f0) || (azt_port == 0x170)) st = check_region(azt_port, 8); /*IDE-interfaces need 8 bytes */ else st = check_region(azt_port, 4); /*proprietary interfaces need 4 bytes */ if (st) { printk ("aztcd: conflict, I/O port (%X) already used\n", azt_port); return -EIO; } if ((azt_port == 0x1f0) || (azt_port == 0x170)) SWITCH_IDE_SLAVE; /*switch IDE interface to slave configuration */ outb(POLLED, MODE_PORT); inb(CMD_PORT); inb(CMD_PORT); outb(ACMD_GET_VERSION, CMD_PORT); /*Try to get version info */ aztTimeOutCount = 0; do { aztIndatum = inb(STATUS_PORT); aztTimeOutCount++; if (aztTimeOutCount >= AZT_FAST_TIMEOUT) break; } while (aztIndatum & AFL_STATUS); if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? If not, reset and try again */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -