static int nftl_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { struct NFTLrecord *nftl; nftl = NFTLs[MINOR(inode->i_rdev) / 16]; if (!nftl) return -EINVAL; switch (cmd) { case HDIO_GETGEO: { struct hd_geometry g; g.heads = nftl->heads; g.sectors = nftl->sectors; g.cylinders = nftl->cylinders; g.start = part_table[MINOR(inode->i_rdev)].start_sect; return copy_to_user((void *)arg, &g, sizeof g) ? -EFAULT : 0; } case BLKGETSIZE: /* Return device size */ if (!arg) return -EINVAL; return put_user(part_table[MINOR(inode->i_rdev)].nr_sects, (long *) arg); case BLKFLSBUF: if (!capable(CAP_SYS_ADMIN)) return -EACCES; fsync_dev(inode->i_rdev); invalidate_buffers(inode->i_rdev); if (nftl->mtd->sync) nftl->mtd->sync(nftl->mtd); return 0; case BLKRRPART: if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (nftl->usecount > 1) return -EBUSY; #if LINUX_VERSION_CODE < 0x20328 resetup_one_dev(&nftl_gendisk, MINOR(inode->i_rdev) / 16); #else grok_partitions(&nftl_gendisk, MINOR(inode->i_rdev) / 16, 1<<4, nftl->nr_sects); #endif return 0; #if (LINUX_VERSION_CODE < 0x20303) RO_IOCTLS(inode->i_rdev, arg); /* ref. linux/blk.h */ #else case BLKROSET: case BLKROGET: case BLKSSZGET: return blk_ioctl(inode->i_rdev, cmd, arg); #endif default: return -EINVAL; } }
static int nftl_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { struct NFTLrecord *nftl; int p; nftl = NFTLs[MINOR(inode->i_rdev) >> NFTL_PARTN_BITS]; if (!nftl) return -EINVAL; switch (cmd) { case HDIO_GETGEO: { struct hd_geometry g; g.heads = nftl->heads; g.sectors = nftl->sectors; g.cylinders = nftl->cylinders; g.start = part_table[MINOR(inode->i_rdev)].start_sect; return copy_to_user((void *)arg, &g, sizeof g) ? -EFAULT : 0; } case BLKGETSIZE: /* Return device size */ return put_user(part_table[MINOR(inode->i_rdev)].nr_sects, (unsigned long *) arg); #ifdef BLKGETSIZE64 case BLKGETSIZE64: return put_user((u64)part_table[MINOR(inode->i_rdev)].nr_sects << 9, (u64 *)arg); #endif case BLKFLSBUF: if (!capable(CAP_SYS_ADMIN)) return -EACCES; fsync_dev(inode->i_rdev); invalidate_buffers(inode->i_rdev); if (nftl->mtd->sync) nftl->mtd->sync(nftl->mtd); return 0; case BLKRRPART: if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (nftl->usecount > 1) return -EBUSY; /* * We have to flush all buffers and invalidate caches, * or we won't be able to re-use the partitions, * if there was a change and we don't want to reboot */ p = (1<<NFTL_PARTN_BITS) - 1; while (p-- > 0) { kdev_t devp = MKDEV(MAJOR(inode->i_dev), MINOR(inode->i_dev)+p); if (part_table[p].nr_sects > 0) invalidate_device (devp, 1); part_table[MINOR(inode->i_dev)+p].start_sect = 0; part_table[MINOR(inode->i_dev)+p].nr_sects = 0; } #if LINUX_VERSION_CODE < 0x20328 resetup_one_dev(&nftl_gendisk, MINOR(inode->i_rdev) >> NFTL_PARTN_BITS); #else grok_partitions(&nftl_gendisk, MINOR(inode->i_rdev) >> NFTL_PARTN_BITS, 1<<NFTL_PARTN_BITS, nftl->nr_sects); #endif return 0; #if (LINUX_VERSION_CODE < 0x20303) RO_IOCTLS(inode->i_rdev, arg); /* ref. linux/blk.h */ #else case BLKROSET: case BLKROGET: case BLKSSZGET: return blk_ioctl(inode->i_rdev, cmd, arg); #endif default: return -EINVAL; } }
int sr_ioctl(struct inode * inode, struct file * file, unsigned long cmd, unsigned long arg) { int dev = inode->i_rdev; int result; target = MINOR(dev); switch (cmd) { /* linux-specific */ case CDROMDOORUNLOCK: lock_sr_ioctl(); sr_cmd[0] = ALLOW_MEDIUM_REMOVAL; sr_cmd[1] = scsi_CDs[target].device->lun << 5; sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0; sr_cmd[4] = SR_REMOVAL_ALLOW; result = do_ioctl(); unlock_sr_ioctl(); return result; case CDROMDOORLOCK: lock_sr_ioctl(); sr_cmd[0] = ALLOW_MEDIUM_REMOVAL; sr_cmd[1] = scsi_CDs[target].device->lun << 5; sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0; sr_cmd[4] = SR_REMOVAL_PREVENT; result = do_ioctl(); unlock_sr_ioctl(); return result; /* Sun-compatible */ case CDROMPAUSE: lock_sr_ioctl(); sr_cmd[0] = SCMD_PAUSE_RESUME; sr_cmd[1] = scsi_CDs[target].device->lun << 5; sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = 0; sr_cmd[5] = sr_cmd[6] = sr_cmd[7] = 0; sr_cmd[8] = 1; sr_cmd[9] = 0; result = do_ioctl(); unlock_sr_ioctl(); return result; case CDROMRESUME: lock_sr_ioctl(); sr_cmd[0] = SCMD_PAUSE_RESUME; sr_cmd[1] = scsi_CDs[target].device->lun << 5; sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = 0; sr_cmd[5] = sr_cmd[6] = sr_cmd[7] = 0; sr_cmd[8] = 0; sr_cmd[9] = 0; result = do_ioctl(); unlock_sr_ioctl(); return result; case CDROMPLAYMSF: { struct cdrom_msf msf; lock_sr_ioctl(); memcpy_fromfs(&msf, (void *) arg, sizeof(msf)); sr_cmd[0] = SCMD_PLAYAUDIO_MSF; sr_cmd[1] = scsi_CDs[target].device->lun << 5; sr_cmd[2] = 0; sr_cmd[3] = msf.cdmsf_min0; sr_cmd[4] = msf.cdmsf_sec0; sr_cmd[5] = msf.cdmsf_frame0; sr_cmd[6] = msf.cdmsf_min1; sr_cmd[7] = msf.cdmsf_sec1; sr_cmd[8] = msf.cdmsf_frame1; sr_cmd[9] = 0; result = do_ioctl(); unlock_sr_ioctl(); return result; } case CDROMPLAYTRKIND: { struct cdrom_ti ti; lock_sr_ioctl(); memcpy_fromfs(&ti, (void *) arg, sizeof(ti)); sr_cmd[0] = SCMD_PLAYAUDIO_TI; sr_cmd[1] = scsi_CDs[target].device->lun << 5; sr_cmd[2] = 0; sr_cmd[3] = 0; sr_cmd[4] = ti.cdti_trk0; sr_cmd[5] = ti.cdti_ind0; sr_cmd[6] = 0; sr_cmd[7] = ti.cdti_trk1; sr_cmd[8] = ti.cdti_ind1; sr_cmd[9] = 0; result = do_ioctl(); unlock_sr_ioctl(); return result; } case CDROMREADTOCHDR: return -EINVAL; case CDROMREADTOCENTRY: return -EINVAL; case CDROMSTOP: lock_sr_ioctl(); 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] = 0; result = do_ioctl(); unlock_sr_ioctl(); return result; case CDROMSTART: lock_sr_ioctl(); 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] = 1; result = do_ioctl(); unlock_sr_ioctl(); return result; case CDROMEJECT: lock_sr_ioctl(); 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; result = do_ioctl(); unlock_sr_ioctl(); return result; case CDROMVOLCTRL: return -EINVAL; case CDROMSUBCHNL: return -EINVAL; case CDROMREADMODE2: return -EINVAL; case CDROMREADMODE1: return -EINVAL; RO_IOCTLS(dev,arg); default: return scsi_ioctl(scsi_CDs[target].device,cmd,(void *) arg); } }
int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { u_char sr_cmd[10]; int dev = inode->i_rdev; int result, target; target = MINOR(dev); if (target >= NR_SR) return -ENODEV; switch (cmd) { /* Sun-compatible */ case CDROMPAUSE: sr_cmd[0] = SCMD_PAUSE_RESUME; sr_cmd[1] = scsi_CDs[target].device->lun << 5; sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = 0; sr_cmd[5] = sr_cmd[6] = sr_cmd[7] = 0; sr_cmd[8] = 0; sr_cmd[9] = 0; result = do_ioctl(target, sr_cmd, NULL, 255); return result; case CDROMRESUME: sr_cmd[0] = SCMD_PAUSE_RESUME; sr_cmd[1] = scsi_CDs[target].device->lun << 5; sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = 0; sr_cmd[5] = sr_cmd[6] = sr_cmd[7] = 0; sr_cmd[8] = 1; sr_cmd[9] = 0; result = do_ioctl(target, sr_cmd, NULL, 255); return result; case CDROMPLAYMSF: { struct cdrom_msf msf; memcpy_fromfs(&msf, (void *) arg, sizeof(msf)); sr_cmd[0] = SCMD_PLAYAUDIO_MSF; sr_cmd[1] = scsi_CDs[target].device->lun << 5; sr_cmd[2] = 0; sr_cmd[3] = msf.cdmsf_min0; sr_cmd[4] = msf.cdmsf_sec0; sr_cmd[5] = msf.cdmsf_frame0; sr_cmd[6] = msf.cdmsf_min1; sr_cmd[7] = msf.cdmsf_sec1; sr_cmd[8] = msf.cdmsf_frame1; sr_cmd[9] = 0; result = do_ioctl(target, sr_cmd, NULL, 255); return result; } case CDROMPLAYTRKIND: { struct cdrom_ti ti; memcpy_fromfs(&ti, (void *) arg, sizeof(ti)); sr_cmd[0] = SCMD_PLAYAUDIO_TI; sr_cmd[1] = scsi_CDs[target].device->lun << 5; sr_cmd[2] = 0; sr_cmd[3] = 0; sr_cmd[4] = ti.cdti_trk0; sr_cmd[5] = ti.cdti_ind0; sr_cmd[6] = 0; sr_cmd[7] = ti.cdti_trk1; sr_cmd[8] = ti.cdti_ind1; sr_cmd[9] = 0; result = do_ioctl(target, sr_cmd, NULL, 255); return result; } case CDROMREADTOCHDR: { struct cdrom_tochdr tochdr; char buffer[12]; sr_cmd[0] = SCMD_READ_TOC; sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02; /* MSF format */ sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0; sr_cmd[6] = 0; sr_cmd[7] = 0; /* MSB of length (12) */ sr_cmd[8] = 12; /* LSB of length */ sr_cmd[9] = 0; result = do_ioctl(target, sr_cmd, buffer, sizeof (buffer)); tochdr.cdth_trk0 = buffer[2]; tochdr.cdth_trk1 = buffer[3]; verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_tochdr)); memcpy_tofs ((void *) arg, &tochdr, sizeof (struct cdrom_tochdr)); return result; } case CDROMREADTOCENTRY: { struct cdrom_tocentry tocentry; char buffer[12]; verify_area (VERIFY_READ, (void *) arg, sizeof (struct cdrom_tocentry)); memcpy_fromfs (&tocentry, (void *) arg, sizeof (struct cdrom_tocentry)); sr_cmd[0] = SCMD_READ_TOC; sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02; /* MSF format */ sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0; sr_cmd[6] = tocentry.cdte_track; sr_cmd[7] = 0; /* MSB of length (12) */ sr_cmd[8] = 12; /* LSB of length */ sr_cmd[9] = 0; result = do_ioctl (target, sr_cmd, buffer, sizeof (buffer)); 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]; tocentry.cdte_ctrl = buffer[5] & 0xf; } else tocentry.cdte_addr.lba = (int) buffer[0]; verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_tocentry)); memcpy_tofs ((void *) arg, &tocentry, sizeof (struct cdrom_tocentry)); return result; } case CDROMSTOP: 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] = 0; result = do_ioctl(target, sr_cmd, NULL, 255); return result; case CDROMSTART: 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] = 1; result = do_ioctl(target, sr_cmd, NULL, 255); return result; case CDROMEJECT: if (scsi_CDs[target].device -> access_count == 1) 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 CDROMVOLCTRL: { char buffer[28], mask[28]; struct cdrom_volctrl volctrl; verify_area (VERIFY_READ, (void *) arg, sizeof (struct cdrom_volctrl)); 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; if ((result = do_ioctl (target, sr_cmd, buffer, sizeof (buffer)))) { printk ("Hosed while obtaining audio mode page\n"); 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; if ((result = do_ioctl (target, sr_cmd, mask, sizeof (mask)))) { printk ("Hosed while obtaining mask for audio mode page\n"); return result; } /* Now mask and substitute our own volume and reuse the rest */ 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, sizeof (buffer)); return result; } case CDROMSUBCHNL: { struct cdrom_subchnl subchnl; char buffer[16]; 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; result = do_ioctl(target, sr_cmd, buffer, sizeof (buffer)); 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]; verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_subchnl)); memcpy_tofs ((void *) arg, &subchnl, sizeof (struct cdrom_subchnl)); return result; } case CDROMREADMODE2: return -EINVAL; case CDROMREADMODE1: return -EINVAL; RO_IOCTLS(dev,arg); default: return scsi_ioctl(scsi_CDs[target].device,cmd,(void *) arg); } }