sr_ioctl.c
来自「GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目」· C语言 代码 · 共 608 行 · 第 1/2 页
C
608 行
sr_cmd[4] = 0x03; if ((result = do_ioctl(target, sr_cmd, NULL, 255))) return result; /* Gather information about newly inserted disc */ check_disk_change (inode->i_rdev); sr_ioctl (inode, NULL, SCSI_IOCTL_DOORLOCK, 0); sr_photocd (inode); if (scsi_CDs[MINOR(inode->i_rdev)].needs_sector_size) get_sectorsize (MINOR(inode->i_rdev)); return 0; case CDROMEJECT: /* * Allow 0 for access count for auto-eject feature. */ if (scsi_CDs[target].device -> access_count > 1) return -EBUSY; sr_ioctl (inode, NULL, SCSI_IOCTL_DOORUNLOCK, 0); sr_cmd[0] = START_STOP; sr_cmd[1] = ((scsi_CDs[target].device -> lun) << 5) | 1; sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0; sr_cmd[4] = 0x02; if (!(result = do_ioctl(target, sr_cmd, NULL, 255))) scsi_CDs[target].device -> changed = 1; return result; case CDROMEJECT_SW: scsi_CDs[target].auto_eject = !!arg; return 0; case CDROMVOLCTRL: { char * buffer, * mask; struct cdrom_volctrl volctrl; err = verify_area (VERIFY_READ, (void *) arg, sizeof (struct cdrom_volctrl)); if (err) return err; memcpy_fromfs (&volctrl, (void *) arg, sizeof (struct cdrom_volctrl)); /* First we get the current params so we can just twiddle the volume */ sr_cmd[0] = MODE_SENSE; sr_cmd[1] = (scsi_CDs[target].device -> lun) << 5; sr_cmd[2] = 0xe; /* Want mode page 0xe, CDROM audio params */ sr_cmd[3] = 0; sr_cmd[4] = 28; sr_cmd[5] = 0; buffer = (unsigned char *) scsi_malloc(512); if(!buffer) return -ENOMEM; if ((result = do_ioctl (target, sr_cmd, buffer, 28))) { printk ("Hosed while obtaining audio mode page\n"); scsi_free(buffer, 512); return result; } sr_cmd[0] = MODE_SENSE; sr_cmd[1] = (scsi_CDs[target].device -> lun) << 5; sr_cmd[2] = 0x4e; /* Want the mask for mode page 0xe */ sr_cmd[3] = 0; sr_cmd[4] = 28; sr_cmd[5] = 0; mask = (unsigned char *) scsi_malloc(512); if(!mask) { scsi_free(buffer, 512); return -ENOMEM; }; if ((result = do_ioctl (target, sr_cmd, mask, 28))) { printk ("Hosed while obtaining mask for audio mode page\n"); scsi_free(buffer, 512); scsi_free(mask, 512); return result; } /* Now mask and substitute our own volume and reuse the rest */ buffer[0] = 0; /* Clear reserved field */ buffer[21] = volctrl.channel0 & mask[21]; buffer[23] = volctrl.channel1 & mask[23]; buffer[25] = volctrl.channel2 & mask[25]; buffer[27] = volctrl.channel3 & mask[27]; sr_cmd[0] = MODE_SELECT; sr_cmd[1] = ((scsi_CDs[target].device -> lun) << 5) | 0x10; /* Params are SCSI-2 */ sr_cmd[2] = sr_cmd[3] = 0; sr_cmd[4] = 28; sr_cmd[5] = 0; result = do_ioctl (target, sr_cmd, buffer, 28); scsi_free(buffer, 512); scsi_free(mask, 512); return result; } case CDROMVOLREAD: { char * buffer; struct cdrom_volctrl volctrl; err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_volctrl)); if (err) return err; /* Get the current params */ sr_cmd[0] = MODE_SENSE; sr_cmd[1] = (scsi_CDs[target].device -> lun) << 5; sr_cmd[2] = 0xe; /* Want mode page 0xe, CDROM audio params */ sr_cmd[3] = 0; sr_cmd[4] = 28; sr_cmd[5] = 0; buffer = (unsigned char *) scsi_malloc(512); if(!buffer) return -ENOMEM; if ((result = do_ioctl (target, sr_cmd, buffer, 28))) { printk ("(CDROMVOLREAD) Hosed while obtaining audio mode page\n"); scsi_free(buffer, 512); return result; } volctrl.channel0 = buffer[21]; volctrl.channel1 = buffer[23]; volctrl.channel2 = buffer[25]; volctrl.channel3 = buffer[27]; memcpy_tofs ((void *) arg, &volctrl, sizeof (struct cdrom_volctrl)); scsi_free(buffer, 512); return 0; } case CDROMSUBCHNL: { struct cdrom_subchnl subchnl; char * buffer; sr_cmd[0] = SCMD_READ_SUBCHANNEL; sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02; /* MSF format */ sr_cmd[2] = 0x40; /* I do want the subchannel info */ sr_cmd[3] = 0x01; /* Give me current position info */ sr_cmd[4] = sr_cmd[5] = 0; sr_cmd[6] = 0; sr_cmd[7] = 0; sr_cmd[8] = 16; sr_cmd[9] = 0; buffer = (unsigned char*) scsi_malloc(512); if(!buffer) return -ENOMEM; result = do_ioctl(target, sr_cmd, buffer, 16); subchnl.cdsc_audiostatus = buffer[1]; subchnl.cdsc_format = CDROM_MSF; subchnl.cdsc_ctrl = buffer[5] & 0xf; subchnl.cdsc_trk = buffer[6]; subchnl.cdsc_ind = buffer[7]; subchnl.cdsc_reladdr.msf.minute = buffer[13]; subchnl.cdsc_reladdr.msf.second = buffer[14]; subchnl.cdsc_reladdr.msf.frame = buffer[15]; subchnl.cdsc_absaddr.msf.minute = buffer[9]; subchnl.cdsc_absaddr.msf.second = buffer[10]; subchnl.cdsc_absaddr.msf.frame = buffer[11]; scsi_free(buffer, 512); err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_subchnl)); if (err) return err; memcpy_tofs ((void *) arg, &subchnl, sizeof (struct cdrom_subchnl)); return result; } case CDROM_GET_UPC: { struct cdrom_mcn mcn; char * buffer; sr_cmd[0] = SCMD_READ_SUBCHANNEL; sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5); sr_cmd[2] = 0x40; /* I do want the subchannel info */ sr_cmd[3] = 0x02; /* Give me medium catalog number info */ sr_cmd[4] = sr_cmd[5] = 0; sr_cmd[6] = 0; sr_cmd[7] = 0; sr_cmd[8] = 24; sr_cmd[9] = 0; buffer = (unsigned char*) scsi_malloc(512); if(!buffer) return -ENOMEM; result = do_ioctl(target, sr_cmd, buffer, 24); memcpy (mcn.medium_catalog_number, buffer + 9, 13); mcn.medium_catalog_number[13] = 0; scsi_free(buffer, 512); err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_mcn)); if (err) return err; memcpy_tofs ((void *) arg, &mcn, sizeof (struct cdrom_mcn)); return result; } /* these are compatible with the ide-cd driver */ case CDROMREADRAW: case CDROMREADMODE1: case CDROMREADMODE2: return -EINVAL; /* block-copy from ../block/sbpcd.c with some adjustments... */ case CDROMMULTISESSION: /* tell start-of-last-session to user */ { struct cdrom_multisession ms_info; long lba; err = verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_multisession)); if (err) return (err); memcpy_fromfs(&ms_info, (void *) arg, sizeof(struct cdrom_multisession)); if (ms_info.addr_format==CDROM_MSF) { /* MSF-bin requested */ lba = scsi_CDs[target].mpcd_sector+CD_BLOCK_OFFSET; ms_info.addr.msf.minute = lba / (CD_SECS*CD_FRAMES); lba %= CD_SECS*CD_FRAMES; ms_info.addr.msf.second = lba / CD_FRAMES; ms_info.addr.msf.frame = lba % CD_FRAMES; } else if (ms_info.addr_format==CDROM_LBA) /* lba requested */ ms_info.addr.lba=scsi_CDs[target].mpcd_sector; else return (-EINVAL); ms_info.xa_flag=scsi_CDs[target].xa_flags & 0x01; err=verify_area(VERIFY_WRITE,(void *) arg, sizeof(struct cdrom_multisession)); if (err) return (err); memcpy_tofs((void *) arg, &ms_info, sizeof(struct cdrom_multisession)); return (0); } case BLKRAGET: if (!arg) return -EINVAL; err = verify_area(VERIFY_WRITE, (int *) arg, sizeof(int)); if (err) return err; put_user(read_ahead[MAJOR(inode->i_rdev)], (int *) arg); return 0; case BLKRASET: if(!suser()) return -EACCES; if(!(inode->i_rdev)) return -EINVAL; if(arg > 0xff) return -EINVAL; read_ahead[MAJOR(inode->i_rdev)] = arg; return 0; RO_IOCTLS(dev,arg); case CDROMRESET: invalidate_buffers(inode->i_rdev); return 0; 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 + =
减小字号Ctrl + -
显示快捷键?