📄 sr_ioctl.c
字号:
sr_cmd[9] = 0; result = sr_do_ioctl(MINOR(cdi->dev), sr_cmd, buffer, 24, 0, SCSI_DATA_READ, NULL); memcpy(mcn->medium_catalog_number, buffer + 9, 13); mcn->medium_catalog_number[13] = 0; return result;}int sr_reset(struct cdrom_device_info *cdi){ invalidate_buffers(cdi->dev); return 0;}int sr_select_speed(struct cdrom_device_info *cdi, int speed){ u_char sr_cmd[MAX_COMMAND_SIZE]; if (speed == 0) speed = 0xffff; /* set to max */ else speed *= 177; /* Nx to kbyte/s */ memset(sr_cmd, 0, MAX_COMMAND_SIZE); sr_cmd[0] = GPCMD_SET_SPEED; /* SET CD SPEED */ sr_cmd[1] = (scsi_CDs[MINOR(cdi->dev)].device->lun) << 5; sr_cmd[2] = (speed >> 8) & 0xff; /* MSB for speed (in kbytes/sec) */ sr_cmd[3] = speed & 0xff; /* LSB */ if (sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL)) return -EIO; return 0;}/* ----------------------------------------------------------------------- *//* this is called by the generic cdrom driver. arg is a _kernel_ pointer, *//* because the generic cdrom driver does the user access stuff for us. *//* only cdromreadtochdr and cdromreadtocentry are left - for use with the *//* sr_disk_status interface for the generic cdrom driver. */int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg){ u_char sr_cmd[10]; int result, target = MINOR(cdi->dev); unsigned char buffer[32]; memset(sr_cmd, 0, sizeof(sr_cmd)); switch (cmd) { case CDROMREADTOCHDR: { struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg; sr_cmd[0] = GPCMD_READ_TOC_PMA_ATIP; sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5); sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0; sr_cmd[8] = 12; /* LSB of length */ result = sr_do_ioctl(target, sr_cmd, buffer, 12, 1, SCSI_DATA_READ, NULL); tochdr->cdth_trk0 = buffer[2]; tochdr->cdth_trk1 = buffer[3]; break; } case CDROMREADTOCENTRY: { struct cdrom_tocentry *tocentry = (struct cdrom_tocentry *) arg; sr_cmd[0] = GPCMD_READ_TOC_PMA_ATIP; sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | (tocentry->cdte_format == CDROM_MSF ? 0x02 : 0); sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0; sr_cmd[6] = tocentry->cdte_track; sr_cmd[8] = 12; /* LSB of length */ result = sr_do_ioctl(target, sr_cmd, buffer, 12, 0, SCSI_DATA_READ, NULL); tocentry->cdte_ctrl = buffer[5] & 0xf; tocentry->cdte_adr = buffer[5] >> 4; tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0; if (tocentry->cdte_format == CDROM_MSF) { tocentry->cdte_addr.msf.minute = buffer[9]; tocentry->cdte_addr.msf.second = buffer[10]; tocentry->cdte_addr.msf.frame = buffer[11]; } else tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8) + buffer[10]) << 8) + buffer[11]; break; } case CDROMPLAYTRKIND: { struct cdrom_ti* ti = (struct cdrom_ti*)arg; sr_cmd[0] = GPCMD_PLAYAUDIO_TI; sr_cmd[1] = scsi_CDs[target].device->lun << 5; sr_cmd[4] = ti->cdti_trk0; sr_cmd[5] = ti->cdti_ind0; sr_cmd[7] = ti->cdti_trk1; sr_cmd[8] = ti->cdti_ind1; result = sr_do_ioctl(target, sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL); if (result == -EDRIVE_CANT_DO_THIS) result = sr_fake_playtrkind(cdi, ti); break; } default: return -EINVAL; }#if 0 if (result) printk("DEBUG: sr_audio: result for ioctl %x: %x\n", cmd, result);#endif return result;}/* ----------------------------------------------------------------------- * a function to read all sorts of funny cdrom sectors using the READ_CD * scsi-3 mmc command * * lba: linear block address * format: 0 = data (anything) * 1 = audio * 2 = data (mode 1) * 3 = data (mode 2) * 4 = data (mode 2 form1) * 5 = data (mode 2 form2) * blksize: 2048 | 2336 | 2340 | 2352 */int sr_read_cd(int minor, unsigned char *dest, int lba, int format, int blksize){ unsigned char cmd[MAX_COMMAND_SIZE];#ifdef DEBUG printk("sr%d: sr_read_cd lba=%d format=%d blksize=%d\n", minor, lba, format, blksize);#endif memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = GPCMD_READ_CD; /* READ_CD */ cmd[1] = (scsi_CDs[minor].device->lun << 5) | ((format & 7) << 2); cmd[2] = (unsigned char) (lba >> 24) & 0xff; cmd[3] = (unsigned char) (lba >> 16) & 0xff; cmd[4] = (unsigned char) (lba >> 8) & 0xff; cmd[5] = (unsigned char) lba & 0xff; cmd[8] = 1; switch (blksize) { case 2336: cmd[9] = 0x58; break; case 2340: cmd[9] = 0x78; break; case 2352: cmd[9] = 0xf8; break; default: cmd[9] = 0x10; break; } return sr_do_ioctl(minor, cmd, dest, blksize, 0, SCSI_DATA_READ, NULL);}/* * read sectors with blocksizes other than 2048 */int sr_read_sector(int minor, int lba, int blksize, unsigned char *dest){ unsigned char cmd[MAX_COMMAND_SIZE]; /* the scsi-command */ int rc; /* we try the READ CD command first... */ if (scsi_CDs[minor].readcd_known) { rc = sr_read_cd(minor, dest, lba, 0, blksize); if (-EDRIVE_CANT_DO_THIS != rc) return rc; scsi_CDs[minor].readcd_known = 0; printk("CDROM does'nt support READ CD (0xbe) command\n"); /* fall & retry the other way */ } /* ... if this fails, we switch the blocksize using MODE SELECT */ if (blksize != scsi_CDs[minor].device->sector_size) { if (0 != (rc = sr_set_blocklength(minor, blksize))) return rc; }#ifdef DEBUG printk("sr%d: sr_read_sector lba=%d blksize=%d\n", minor, lba, blksize);#endif memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = GPCMD_READ_10; cmd[1] = (scsi_CDs[minor].device->lun << 5); cmd[2] = (unsigned char) (lba >> 24) & 0xff; cmd[3] = (unsigned char) (lba >> 16) & 0xff; cmd[4] = (unsigned char) (lba >> 8) & 0xff; cmd[5] = (unsigned char) lba & 0xff; cmd[8] = 1; rc = sr_do_ioctl(minor, cmd, dest, blksize, 0, SCSI_DATA_READ, NULL); return rc;}/* * read a sector in raw mode to check the sector format * ret: 1 == mode2 (XA), 0 == mode1, <0 == error */int sr_is_xa(int minor){ unsigned char *raw_sector; int is_xa; if (!xa_test) return 0; raw_sector = (unsigned char *) scsi_malloc(2048 + 512); if (!raw_sector) return -ENOMEM; if (0 == sr_read_sector(minor, scsi_CDs[minor].ms_offset + 16, CD_FRAMESIZE_RAW1, raw_sector)) { is_xa = (raw_sector[3] == 0x02) ? 1 : 0; } else { /* read a raw sector failed for some reason. */ is_xa = -1; } scsi_free(raw_sector, 2048 + 512);#ifdef DEBUG printk("sr%d: sr_is_xa: %d\n", minor, is_xa);#endif return is_xa;}int sr_dev_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, unsigned long arg){ int target; target = MINOR(cdi->dev); switch (cmd) { case BLKROSET: case BLKROGET: case BLKRASET: case BLKRAGET: case BLKFLSBUF: case BLKSSZGET: return blk_ioctl(cdi->dev, cmd, arg); default: return scsi_ioctl(scsi_CDs[target].device, cmd, (void *) arg); }}/* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically * adjust the settings for this buffer only. This must remain at the end * of the file. * --------------------------------------------------------------------------- * Local variables: * c-indent-level: 4 * c-brace-imaginary-offset: 0 * c-brace-offset: -4 * c-argdecl-indent: 4 * c-label-offset: -4 * c-continued-statement-offset: 4 * c-continued-brace-offset: 0 * indent-tabs-mode: nil * tab-width: 8 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -