|
|
1.1 ! root 1: #include <linux/config.h> ! 2: #ifdef CONFIG_BLK_DEV_SR ! 3: #include <linux/kernel.h> ! 4: #include <linux/sched.h> ! 5: #include <linux/fs.h> ! 6: #include <asm/segment.h> ! 7: #include <linux/errno.h> ! 8: ! 9: #include "../blk.h" ! 10: #include "scsi.h" ! 11: #include "sr.h" ! 12: ! 13: #include <linux/cdrom.h> ! 14: ! 15: #define IOCTL_RETRIES 3 ! 16: /* The CDROM is fairly slow, so we need a little extra time */ ! 17: #define IOCTL_TIMEOUT 200 ! 18: ! 19: static u_char sr_cmd[10]; ! 20: static u_char data_buffer[255]; ! 21: static u_char sense_buffer[255]; ! 22: static int the_result; ! 23: ! 24: static struct wait_queue *sr_cmd_wait = NULL; /* For waiting until cmd done*/ ! 25: static u_char sr_lock = 0; /* To make sure that only one person is doing ! 26: an ioctl at one time */ ! 27: static int target; ! 28: ! 29: extern int scsi_ioctl (int dev, int cmd, void *arg); ! 30: ! 31: static void lock_sr_ioctl( void ) ! 32: { ! 33: /* We do not use wakeup here because there could conceivably be three ! 34: processes trying to get at the drive simultaneously, and we would ! 35: be screwed if that happened. ! 36: */ ! 37: ! 38: while (sr_lock); ! 39: sr_lock = 1; ! 40: } ! 41: ! 42: static void unlock_sr_ioctl( void ) ! 43: { ! 44: sr_lock = 0; ! 45: } ! 46: ! 47: static void sr_ioctl_done( int host, int result ) ! 48: { ! 49: the_result = result; ! 50: wake_up(&sr_cmd_wait); ! 51: } ! 52: ! 53: /* We do our own retries because we want to know what the specific ! 54: error code is. Normally the UNIT_ATTENTION code will automatically ! 55: clear after one error */ ! 56: ! 57: static int do_ioctl( void ) ! 58: { ! 59: int retries = IOCTL_RETRIES; ! 60: retry: ! 61: ! 62: the_result = -1; ! 63: ! 64: scsi_do_cmd(scsi_CDs[target].device->host_no, scsi_CDs[target].device->id, ! 65: (void *) sr_cmd, (void *) data_buffer, 255, sr_ioctl_done, ! 66: IOCTL_TIMEOUT, (void *) sense_buffer, 0); ! 67: ! 68: while (the_result < 0) sleep_on(&sr_cmd_wait); ! 69: ! 70: if(driver_byte(the_result) != 0 && ! 71: (sense_buffer[2] & 0xf) == UNIT_ATTENTION) { ! 72: scsi_CDs[target].changed = 1; ! 73: printk("Disc change detected.\n"); ! 74: }; ! 75: ! 76: if (the_result && retries) ! 77: { ! 78: retries--; ! 79: goto retry; ! 80: } ! 81: ! 82: /* Minimal error checking. Ignore cases we know about, and report the rest. */ ! 83: if(driver_byte(the_result) != 0) ! 84: switch(sense_buffer[2] & 0xf) { ! 85: case UNIT_ATTENTION: ! 86: scsi_CDs[target].changed = 1; ! 87: printk("Disc change detected.\n"); ! 88: break; ! 89: case NOT_READY: /* This happens if there is no disc in drive */ ! 90: printk("CDROM not ready. Make sure there is a disc in the drive.\n"); ! 91: break; ! 92: case ILLEGAL_REQUEST: ! 93: printk("CDROM (ioctl) reports ILLEGAL REQUEST.\n"); ! 94: break; ! 95: default: ! 96: printk("SCSI CD error: host %d id %d lun %d return code = %03x\n", ! 97: scsi_CDs[target].device->host_no, ! 98: scsi_CDs[target].device->id, ! 99: scsi_CDs[target].device->lun, ! 100: the_result); ! 101: printk("\tSense class %x, sense error %x, extended sense %x\n", ! 102: sense_class(sense_buffer[0]), ! 103: sense_error(sense_buffer[0]), ! 104: sense_buffer[2] & 0xf); ! 105: ! 106: }; ! 107: return the_result; ! 108: } ! 109: ! 110: /* ! 111: * This function checks to see if the media has been changed in the ! 112: * CDROM drive. It is possible that we have already sensed a change, ! 113: * or the drive may have sensed one and not yet reported it. We must ! 114: * be ready for either case. This function always reports the current ! 115: * value of the changed bit. If flag is 0, then the changed bit is reset. ! 116: * This function could be done as an ioctl, but we would need to have ! 117: * an inode for that to work, and we do not always have one. ! 118: */ ! 119: ! 120: int check_cdrom_media_change(int full_dev, int flag){ ! 121: int retval; ! 122: ! 123: lock_sr_ioctl(); ! 124: ! 125: target = MINOR(full_dev); ! 126: ! 127: if (target >= NR_SR) { ! 128: printk("CD-ROM request error: invalid device.\n"); ! 129: unlock_sr_ioctl(); ! 130: return 0; ! 131: }; ! 132: ! 133: sr_cmd[0] = TEST_UNIT_READY; ! 134: sr_cmd[1] = (scsi_CDs[target].device->lun << 5) & 0xe0; ! 135: sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0; ! 136: ! 137: retval = do_ioctl(); ! 138: ! 139: if(retval){ /* Unable to test, unit probably not ready. This usually ! 140: means there is no disc in the drive. Mark as changed, ! 141: and we will figure it out later once the drive is ! 142: available again. */ ! 143: ! 144: scsi_CDs[target].changed = 1; ! 145: unlock_sr_ioctl(); ! 146: return 1; /* This will force a flush, if called from ! 147: check_disk_change */ ! 148: }; ! 149: ! 150: retval = scsi_CDs[target].changed; ! 151: if(!flag) scsi_CDs[target].changed = 0; ! 152: unlock_sr_ioctl(); ! 153: ! 154: return retval; ! 155: } ! 156: ! 157: int sr_ioctl(struct inode * inode, struct file * file, unsigned long cmd, unsigned long arg) ! 158: { ! 159: int dev = inode->i_rdev; ! 160: int result; ! 161: ! 162: target = MINOR(dev); ! 163: ! 164: switch (cmd) ! 165: { ! 166: /* linux-specific */ ! 167: case CDROMDOORUNLOCK: ! 168: lock_sr_ioctl(); ! 169: ! 170: sr_cmd[0] = ALLOW_MEDIUM_REMOVAL; ! 171: sr_cmd[1] = scsi_CDs[target].device->lun << 5; ! 172: sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0; ! 173: sr_cmd[4] = SR_REMOVAL_ALLOW; ! 174: ! 175: result = do_ioctl(); ! 176: ! 177: unlock_sr_ioctl(); ! 178: return result; ! 179: ! 180: case CDROMDOORLOCK: ! 181: lock_sr_ioctl(); ! 182: ! 183: sr_cmd[0] = ALLOW_MEDIUM_REMOVAL; ! 184: sr_cmd[1] = scsi_CDs[target].device->lun << 5; ! 185: sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0; ! 186: sr_cmd[4] = SR_REMOVAL_PREVENT; ! 187: ! 188: result = do_ioctl(); ! 189: ! 190: unlock_sr_ioctl(); ! 191: return result; ! 192: ! 193: /* Sun-compatible */ ! 194: case CDROMPAUSE: ! 195: lock_sr_ioctl(); ! 196: ! 197: sr_cmd[0] = SCMD_PAUSE_RESUME; ! 198: sr_cmd[1] = scsi_CDs[target].device->lun << 5; ! 199: sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = 0; ! 200: sr_cmd[5] = sr_cmd[6] = sr_cmd[7] = 0; ! 201: sr_cmd[8] = 1; ! 202: sr_cmd[9] = 0; ! 203: ! 204: result = do_ioctl(); ! 205: ! 206: unlock_sr_ioctl(); ! 207: return result; ! 208: ! 209: case CDROMRESUME: ! 210: lock_sr_ioctl(); ! 211: ! 212: sr_cmd[0] = SCMD_PAUSE_RESUME; ! 213: sr_cmd[1] = scsi_CDs[target].device->lun << 5; ! 214: sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = 0; ! 215: sr_cmd[5] = sr_cmd[6] = sr_cmd[7] = 0; ! 216: sr_cmd[8] = 0; ! 217: sr_cmd[9] = 0; ! 218: ! 219: result = do_ioctl(); ! 220: ! 221: unlock_sr_ioctl(); ! 222: return result; ! 223: ! 224: case CDROMPLAYMSF: ! 225: { ! 226: struct cdrom_msf msf; ! 227: lock_sr_ioctl(); ! 228: ! 229: memcpy_fromfs(&msf, (void *) arg, sizeof(msf)); ! 230: ! 231: sr_cmd[0] = SCMD_PLAYAUDIO_MSF; ! 232: sr_cmd[1] = scsi_CDs[target].device->lun << 5; ! 233: sr_cmd[2] = 0; ! 234: sr_cmd[3] = msf.cdmsf_min0; ! 235: sr_cmd[4] = msf.cdmsf_sec0; ! 236: sr_cmd[5] = msf.cdmsf_frame0; ! 237: sr_cmd[6] = msf.cdmsf_min1; ! 238: sr_cmd[7] = msf.cdmsf_sec1; ! 239: sr_cmd[8] = msf.cdmsf_frame1; ! 240: sr_cmd[9] = 0; ! 241: ! 242: result = do_ioctl(); ! 243: ! 244: unlock_sr_ioctl(); ! 245: return result; ! 246: } ! 247: ! 248: case CDROMPLAYTRKIND: ! 249: { ! 250: struct cdrom_ti ti; ! 251: lock_sr_ioctl(); ! 252: ! 253: memcpy_fromfs(&ti, (void *) arg, sizeof(ti)); ! 254: ! 255: sr_cmd[0] = SCMD_PLAYAUDIO_TI; ! 256: sr_cmd[1] = scsi_CDs[target].device->lun << 5; ! 257: sr_cmd[2] = 0; ! 258: sr_cmd[3] = 0; ! 259: sr_cmd[4] = ti.cdti_trk0; ! 260: sr_cmd[5] = ti.cdti_ind0; ! 261: sr_cmd[6] = 0; ! 262: sr_cmd[7] = ti.cdti_trk1; ! 263: sr_cmd[8] = ti.cdti_ind1; ! 264: sr_cmd[9] = 0; ! 265: ! 266: result = do_ioctl(); ! 267: ! 268: unlock_sr_ioctl(); ! 269: return result; ! 270: } ! 271: ! 272: case CDROMREADTOCHDR: ! 273: return -EINVAL; ! 274: case CDROMREADTOCENTRY: ! 275: return -EINVAL; ! 276: ! 277: case CDROMSTOP: ! 278: lock_sr_ioctl(); ! 279: ! 280: sr_cmd[0] = START_STOP; ! 281: sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1; ! 282: sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0; ! 283: sr_cmd[4] = 0; ! 284: ! 285: result = do_ioctl(); ! 286: ! 287: unlock_sr_ioctl(); ! 288: return result; ! 289: ! 290: case CDROMSTART: ! 291: lock_sr_ioctl(); ! 292: ! 293: sr_cmd[0] = START_STOP; ! 294: sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1; ! 295: sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0; ! 296: sr_cmd[4] = 1; ! 297: ! 298: result = do_ioctl(); ! 299: ! 300: unlock_sr_ioctl(); ! 301: return result; ! 302: ! 303: case CDROMEJECT: ! 304: lock_sr_ioctl(); ! 305: ! 306: sr_cmd[0] = START_STOP; ! 307: sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1; ! 308: sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0; ! 309: sr_cmd[4] = 0x02; ! 310: ! 311: result = do_ioctl(); ! 312: ! 313: unlock_sr_ioctl(); ! 314: return result; ! 315: ! 316: case CDROMVOLCTRL: ! 317: return -EINVAL; ! 318: case CDROMSUBCHNL: ! 319: return -EINVAL; ! 320: case CDROMREADMODE2: ! 321: return -EINVAL; ! 322: case CDROMREADMODE1: ! 323: return -EINVAL; ! 324: ! 325: RO_IOCTLS(dev,arg); ! 326: default: ! 327: return scsi_ioctl(scsi_CDs[target].device,cmd,(void *) arg); ! 328: } ! 329: } ! 330: ! 331: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.