|
|
1.1 ! root 1: #include <linux/kernel.h> ! 2: #include <linux/sched.h> ! 3: #include <linux/mm.h> ! 4: #include <linux/fs.h> ! 5: #include <asm/segment.h> ! 6: #include <linux/errno.h> ! 7: #include <linux/string.h> ! 8: ! 9: #include <linux/blk.h> ! 10: #include "scsi.h" ! 11: #include "hosts.h" ! 12: #include "sr.h" ! 13: #include <scsi/scsi_ioctl.h> ! 14: ! 15: #include <linux/cdrom.h> ! 16: ! 17: extern void get_sectorsize(int); ! 18: extern void sr_photocd(struct inode *); ! 19: ! 20: #define IOCTL_RETRIES 3 ! 21: /* The CDROM is fairly slow, so we need a little extra time */ ! 22: /* In fact, it is very slow if it has to spin up first */ ! 23: #define IOCTL_TIMEOUT 3000 ! 24: ! 25: static void sr_ioctl_done(Scsi_Cmnd * SCpnt) ! 26: { ! 27: struct request * req; ! 28: ! 29: req = &SCpnt->request; ! 30: req->rq_status = RQ_SCSI_DONE; /* Busy, but indicate request done */ ! 31: ! 32: if (req->sem != NULL) { ! 33: up(req->sem); ! 34: } ! 35: } ! 36: ! 37: /* We do our own retries because we want to know what the specific ! 38: error code is. Normally the UNIT_ATTENTION code will automatically ! 39: clear after one error */ ! 40: ! 41: static int do_ioctl(int target, unsigned char * sr_cmd, void * buffer, unsigned buflength) ! 42: { ! 43: Scsi_Cmnd * SCpnt; ! 44: int result; ! 45: ! 46: SCpnt = allocate_device(NULL, scsi_CDs[target].device, 1); ! 47: { ! 48: struct semaphore sem = MUTEX_LOCKED; ! 49: SCpnt->request.sem = &sem; ! 50: scsi_do_cmd(SCpnt, ! 51: (void *) sr_cmd, buffer, buflength, sr_ioctl_done, ! 52: IOCTL_TIMEOUT, IOCTL_RETRIES); ! 53: down(&sem); ! 54: } ! 55: ! 56: result = SCpnt->result; ! 57: ! 58: /* Minimal error checking. Ignore cases we know about, and report the rest. */ ! 59: if(driver_byte(result) != 0) ! 60: switch(SCpnt->sense_buffer[2] & 0xf) { ! 61: case UNIT_ATTENTION: ! 62: scsi_CDs[target].device->changed = 1; ! 63: printk("Disc change detected.\n"); ! 64: break; ! 65: case NOT_READY: /* This happens if there is no disc in drive */ ! 66: printk("CDROM not ready. Make sure there is a disc in the drive.\n"); ! 67: break; ! 68: case ILLEGAL_REQUEST: ! 69: /* CDROMCLOSETRAY should not print an error for caddy drives. */ ! 70: if (!(sr_cmd[0] == START_STOP && sr_cmd[4] == 0x03)) ! 71: printk("CDROM (ioctl) reports ILLEGAL REQUEST.\n"); ! 72: break; ! 73: default: ! 74: printk("SCSI CD error: host %d id %d lun %d return code = %03x\n", ! 75: scsi_CDs[target].device->host->host_no, ! 76: scsi_CDs[target].device->id, ! 77: scsi_CDs[target].device->lun, ! 78: result); ! 79: printk("\tSense class %x, sense error %x, extended sense %x\n", ! 80: sense_class(SCpnt->sense_buffer[0]), ! 81: sense_error(SCpnt->sense_buffer[0]), ! 82: SCpnt->sense_buffer[2] & 0xf); ! 83: ! 84: }; ! 85: ! 86: result = SCpnt->result; ! 87: SCpnt->request.rq_status = RQ_INACTIVE; /* Deallocate */ ! 88: wake_up(&SCpnt->device->device_wait); ! 89: /* Wake up a process waiting for device*/ ! 90: return result; ! 91: } ! 92: ! 93: int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) ! 94: { ! 95: u_char sr_cmd[10]; ! 96: ! 97: kdev_t dev = inode->i_rdev; ! 98: int result, target, err; ! 99: ! 100: target = MINOR(dev); ! 101: ! 102: if (target >= sr_template.nr_dev || ! 103: !scsi_CDs[target].device) return -ENXIO; ! 104: ! 105: switch (cmd) ! 106: { ! 107: /* Sun-compatible */ ! 108: case CDROMPAUSE: ! 109: ! 110: sr_cmd[0] = SCMD_PAUSE_RESUME; ! 111: sr_cmd[1] = scsi_CDs[target].device->lun << 5; ! 112: sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = 0; ! 113: sr_cmd[5] = sr_cmd[6] = sr_cmd[7] = 0; ! 114: sr_cmd[8] = 0; ! 115: sr_cmd[9] = 0; ! 116: ! 117: result = do_ioctl(target, sr_cmd, NULL, 255); ! 118: return result; ! 119: ! 120: case CDROMRESUME: ! 121: ! 122: sr_cmd[0] = SCMD_PAUSE_RESUME; ! 123: sr_cmd[1] = scsi_CDs[target].device->lun << 5; ! 124: sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = 0; ! 125: sr_cmd[5] = sr_cmd[6] = sr_cmd[7] = 0; ! 126: sr_cmd[8] = 1; ! 127: sr_cmd[9] = 0; ! 128: ! 129: result = do_ioctl(target, sr_cmd, NULL, 255); ! 130: ! 131: return result; ! 132: ! 133: case CDROMPLAYMSF: ! 134: { ! 135: struct cdrom_msf msf; ! 136: ! 137: err = verify_area (VERIFY_READ, (void *) arg, sizeof (msf)); ! 138: if (err) return err; ! 139: ! 140: memcpy_fromfs(&msf, (void *) arg, sizeof(msf)); ! 141: ! 142: sr_cmd[0] = SCMD_PLAYAUDIO_MSF; ! 143: sr_cmd[1] = scsi_CDs[target].device->lun << 5; ! 144: sr_cmd[2] = 0; ! 145: sr_cmd[3] = msf.cdmsf_min0; ! 146: sr_cmd[4] = msf.cdmsf_sec0; ! 147: sr_cmd[5] = msf.cdmsf_frame0; ! 148: sr_cmd[6] = msf.cdmsf_min1; ! 149: sr_cmd[7] = msf.cdmsf_sec1; ! 150: sr_cmd[8] = msf.cdmsf_frame1; ! 151: sr_cmd[9] = 0; ! 152: ! 153: result = do_ioctl(target, sr_cmd, NULL, 255); ! 154: return result; ! 155: } ! 156: ! 157: case CDROMPLAYBLK: ! 158: { ! 159: struct cdrom_blk blk; ! 160: ! 161: err = verify_area (VERIFY_READ, (void *) arg, sizeof (blk)); ! 162: if (err) return err; ! 163: ! 164: memcpy_fromfs(&blk, (void *) arg, sizeof(blk)); ! 165: ! 166: sr_cmd[0] = SCMD_PLAYAUDIO10; ! 167: sr_cmd[1] = scsi_CDs[target].device->lun << 5; ! 168: sr_cmd[2] = blk.from >> 24; ! 169: sr_cmd[3] = blk.from >> 16; ! 170: sr_cmd[4] = blk.from >> 8; ! 171: sr_cmd[5] = blk.from; ! 172: sr_cmd[6] = 0; ! 173: sr_cmd[7] = blk.len >> 8; ! 174: sr_cmd[8] = blk.len; ! 175: sr_cmd[9] = 0; ! 176: ! 177: result = do_ioctl(target, sr_cmd, NULL, 255); ! 178: return result; ! 179: } ! 180: ! 181: case CDROMPLAYTRKIND: ! 182: { ! 183: struct cdrom_ti ti; ! 184: ! 185: err = verify_area (VERIFY_READ, (void *) arg, sizeof (ti)); ! 186: if (err) return err; ! 187: ! 188: memcpy_fromfs(&ti, (void *) arg, sizeof(ti)); ! 189: ! 190: sr_cmd[0] = SCMD_PLAYAUDIO_TI; ! 191: sr_cmd[1] = scsi_CDs[target].device->lun << 5; ! 192: sr_cmd[2] = 0; ! 193: sr_cmd[3] = 0; ! 194: sr_cmd[4] = ti.cdti_trk0; ! 195: sr_cmd[5] = ti.cdti_ind0; ! 196: sr_cmd[6] = 0; ! 197: sr_cmd[7] = ti.cdti_trk1; ! 198: sr_cmd[8] = ti.cdti_ind1; ! 199: sr_cmd[9] = 0; ! 200: ! 201: result = do_ioctl(target, sr_cmd, NULL, 255); ! 202: ! 203: return result; ! 204: } ! 205: ! 206: case CDROMREADTOCHDR: ! 207: { ! 208: struct cdrom_tochdr tochdr; ! 209: char * buffer; ! 210: ! 211: sr_cmd[0] = SCMD_READ_TOC; ! 212: sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5); ! 213: sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0; ! 214: sr_cmd[6] = 0; ! 215: sr_cmd[7] = 0; /* MSB of length (12) */ ! 216: sr_cmd[8] = 12; /* LSB of length */ ! 217: sr_cmd[9] = 0; ! 218: ! 219: buffer = (unsigned char *) scsi_malloc(512); ! 220: if(!buffer) return -ENOMEM; ! 221: ! 222: result = do_ioctl(target, sr_cmd, buffer, 12); ! 223: ! 224: tochdr.cdth_trk0 = buffer[2]; ! 225: tochdr.cdth_trk1 = buffer[3]; ! 226: ! 227: scsi_free(buffer, 512); ! 228: ! 229: err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_tochdr)); ! 230: if (err) ! 231: return err; ! 232: memcpy_tofs ((void *) arg, &tochdr, sizeof (struct cdrom_tochdr)); ! 233: ! 234: return result; ! 235: } ! 236: ! 237: case CDROMREADTOCENTRY: ! 238: { ! 239: struct cdrom_tocentry tocentry; ! 240: unsigned char * buffer; ! 241: ! 242: err = verify_area (VERIFY_READ, (void *) arg, sizeof (struct cdrom_tocentry)); ! 243: if (err) return err; ! 244: ! 245: memcpy_fromfs (&tocentry, (void *) arg, sizeof (struct cdrom_tocentry)); ! 246: ! 247: sr_cmd[0] = SCMD_READ_TOC; ! 248: sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | ! 249: (tocentry.cdte_format == CDROM_MSF ? 0x02 : 0); ! 250: sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0; ! 251: sr_cmd[6] = tocentry.cdte_track; ! 252: sr_cmd[7] = 0; /* MSB of length (12) */ ! 253: sr_cmd[8] = 12; /* LSB of length */ ! 254: sr_cmd[9] = 0; ! 255: ! 256: buffer = (unsigned char *) scsi_malloc(512); ! 257: if(!buffer) return -ENOMEM; ! 258: ! 259: result = do_ioctl (target, sr_cmd, buffer, 12); ! 260: ! 261: tocentry.cdte_ctrl = buffer[5] & 0xf; ! 262: tocentry.cdte_adr = buffer[5] >> 4; ! 263: tocentry.cdte_datamode = (tocentry.cdte_ctrl & 0x04) ? 1 : 0; ! 264: if (tocentry.cdte_format == CDROM_MSF) { ! 265: tocentry.cdte_addr.msf.minute = buffer[9]; ! 266: tocentry.cdte_addr.msf.second = buffer[10]; ! 267: tocentry.cdte_addr.msf.frame = buffer[11]; ! 268: } ! 269: else ! 270: tocentry.cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8) ! 271: + buffer[10]) << 8) + buffer[11]; ! 272: ! 273: scsi_free(buffer, 512); ! 274: ! 275: err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_tocentry)); ! 276: if (err) ! 277: return err; ! 278: memcpy_tofs ((void *) arg, &tocentry, sizeof (struct cdrom_tocentry)); ! 279: ! 280: return result; ! 281: } ! 282: ! 283: case CDROMSTOP: ! 284: sr_cmd[0] = START_STOP; ! 285: sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1; ! 286: sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0; ! 287: sr_cmd[4] = 0; ! 288: ! 289: result = do_ioctl(target, sr_cmd, NULL, 255); ! 290: return result; ! 291: ! 292: case CDROMSTART: ! 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(target, sr_cmd, NULL, 255); ! 299: return result; ! 300: ! 301: case CDROMCLOSETRAY: ! 302: sr_cmd[0] = START_STOP; ! 303: sr_cmd[1] = ((scsi_CDs[target].device -> lun) << 5); ! 304: sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0; ! 305: sr_cmd[4] = 0x03; ! 306: ! 307: if ((result = do_ioctl(target, sr_cmd, NULL, 255))) ! 308: return result; ! 309: ! 310: /* Gather information about newly inserted disc */ ! 311: check_disk_change (inode->i_rdev); ! 312: sr_ioctl (inode, NULL, SCSI_IOCTL_DOORLOCK, 0); ! 313: sr_photocd (inode); ! 314: ! 315: if (scsi_CDs[MINOR(inode->i_rdev)].needs_sector_size) ! 316: get_sectorsize (MINOR(inode->i_rdev)); ! 317: ! 318: return 0; ! 319: ! 320: case CDROMEJECT: ! 321: /* ! 322: * Allow 0 for access count for auto-eject feature. ! 323: */ ! 324: if (scsi_CDs[target].device -> access_count > 1) ! 325: return -EBUSY; ! 326: ! 327: sr_ioctl (inode, NULL, SCSI_IOCTL_DOORUNLOCK, 0); ! 328: sr_cmd[0] = START_STOP; ! 329: sr_cmd[1] = ((scsi_CDs[target].device -> lun) << 5) | 1; ! 330: sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0; ! 331: sr_cmd[4] = 0x02; ! 332: ! 333: if (!(result = do_ioctl(target, sr_cmd, NULL, 255))) ! 334: scsi_CDs[target].device -> changed = 1; ! 335: ! 336: return result; ! 337: ! 338: case CDROMEJECT_SW: ! 339: scsi_CDs[target].auto_eject = !!arg; ! 340: return 0; ! 341: ! 342: case CDROMVOLCTRL: ! 343: { ! 344: char * buffer, * mask; ! 345: struct cdrom_volctrl volctrl; ! 346: ! 347: err = verify_area (VERIFY_READ, (void *) arg, sizeof (struct cdrom_volctrl)); ! 348: if (err) return err; ! 349: ! 350: memcpy_fromfs (&volctrl, (void *) arg, sizeof (struct cdrom_volctrl)); ! 351: ! 352: /* First we get the current params so we can just twiddle the volume */ ! 353: ! 354: sr_cmd[0] = MODE_SENSE; ! 355: sr_cmd[1] = (scsi_CDs[target].device -> lun) << 5; ! 356: sr_cmd[2] = 0xe; /* Want mode page 0xe, CDROM audio params */ ! 357: sr_cmd[3] = 0; ! 358: sr_cmd[4] = 28; ! 359: sr_cmd[5] = 0; ! 360: ! 361: buffer = (unsigned char *) scsi_malloc(512); ! 362: if(!buffer) return -ENOMEM; ! 363: ! 364: if ((result = do_ioctl (target, sr_cmd, buffer, 28))) { ! 365: printk ("Hosed while obtaining audio mode page\n"); ! 366: scsi_free(buffer, 512); ! 367: return result; ! 368: } ! 369: ! 370: sr_cmd[0] = MODE_SENSE; ! 371: sr_cmd[1] = (scsi_CDs[target].device -> lun) << 5; ! 372: sr_cmd[2] = 0x4e; /* Want the mask for mode page 0xe */ ! 373: sr_cmd[3] = 0; ! 374: sr_cmd[4] = 28; ! 375: sr_cmd[5] = 0; ! 376: ! 377: mask = (unsigned char *) scsi_malloc(512); ! 378: if(!mask) { ! 379: scsi_free(buffer, 512); ! 380: return -ENOMEM; ! 381: }; ! 382: ! 383: if ((result = do_ioctl (target, sr_cmd, mask, 28))) { ! 384: printk ("Hosed while obtaining mask for audio mode page\n"); ! 385: scsi_free(buffer, 512); ! 386: scsi_free(mask, 512); ! 387: return result; ! 388: } ! 389: ! 390: /* Now mask and substitute our own volume and reuse the rest */ ! 391: buffer[0] = 0; /* Clear reserved field */ ! 392: ! 393: buffer[21] = volctrl.channel0 & mask[21]; ! 394: buffer[23] = volctrl.channel1 & mask[23]; ! 395: buffer[25] = volctrl.channel2 & mask[25]; ! 396: buffer[27] = volctrl.channel3 & mask[27]; ! 397: ! 398: sr_cmd[0] = MODE_SELECT; ! 399: sr_cmd[1] = ((scsi_CDs[target].device -> lun) << 5) | 0x10; /* Params are SCSI-2 */ ! 400: sr_cmd[2] = sr_cmd[3] = 0; ! 401: sr_cmd[4] = 28; ! 402: sr_cmd[5] = 0; ! 403: ! 404: result = do_ioctl (target, sr_cmd, buffer, 28); ! 405: scsi_free(buffer, 512); ! 406: scsi_free(mask, 512); ! 407: return result; ! 408: } ! 409: ! 410: case CDROMVOLREAD: ! 411: { ! 412: char * buffer; ! 413: struct cdrom_volctrl volctrl; ! 414: ! 415: err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_volctrl)); ! 416: if (err) return err; ! 417: ! 418: /* Get the current params */ ! 419: ! 420: sr_cmd[0] = MODE_SENSE; ! 421: sr_cmd[1] = (scsi_CDs[target].device -> lun) << 5; ! 422: sr_cmd[2] = 0xe; /* Want mode page 0xe, CDROM audio params */ ! 423: sr_cmd[3] = 0; ! 424: sr_cmd[4] = 28; ! 425: sr_cmd[5] = 0; ! 426: ! 427: buffer = (unsigned char *) scsi_malloc(512); ! 428: if(!buffer) return -ENOMEM; ! 429: ! 430: if ((result = do_ioctl (target, sr_cmd, buffer, 28))) { ! 431: printk ("(CDROMVOLREAD) Hosed while obtaining audio mode page\n"); ! 432: scsi_free(buffer, 512); ! 433: return result; ! 434: } ! 435: ! 436: volctrl.channel0 = buffer[21]; ! 437: volctrl.channel1 = buffer[23]; ! 438: volctrl.channel2 = buffer[25]; ! 439: volctrl.channel3 = buffer[27]; ! 440: ! 441: memcpy_tofs ((void *) arg, &volctrl, sizeof (struct cdrom_volctrl)); ! 442: ! 443: scsi_free(buffer, 512); ! 444: ! 445: return 0; ! 446: } ! 447: ! 448: case CDROMSUBCHNL: ! 449: { ! 450: struct cdrom_subchnl subchnl; ! 451: char * buffer; ! 452: ! 453: sr_cmd[0] = SCMD_READ_SUBCHANNEL; ! 454: sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02; /* MSF format */ ! 455: sr_cmd[2] = 0x40; /* I do want the subchannel info */ ! 456: sr_cmd[3] = 0x01; /* Give me current position info */ ! 457: sr_cmd[4] = sr_cmd[5] = 0; ! 458: sr_cmd[6] = 0; ! 459: sr_cmd[7] = 0; ! 460: sr_cmd[8] = 16; ! 461: sr_cmd[9] = 0; ! 462: ! 463: buffer = (unsigned char*) scsi_malloc(512); ! 464: if(!buffer) return -ENOMEM; ! 465: ! 466: result = do_ioctl(target, sr_cmd, buffer, 16); ! 467: ! 468: subchnl.cdsc_audiostatus = buffer[1]; ! 469: subchnl.cdsc_format = CDROM_MSF; ! 470: subchnl.cdsc_ctrl = buffer[5] & 0xf; ! 471: subchnl.cdsc_trk = buffer[6]; ! 472: subchnl.cdsc_ind = buffer[7]; ! 473: ! 474: subchnl.cdsc_reladdr.msf.minute = buffer[13]; ! 475: subchnl.cdsc_reladdr.msf.second = buffer[14]; ! 476: subchnl.cdsc_reladdr.msf.frame = buffer[15]; ! 477: subchnl.cdsc_absaddr.msf.minute = buffer[9]; ! 478: subchnl.cdsc_absaddr.msf.second = buffer[10]; ! 479: subchnl.cdsc_absaddr.msf.frame = buffer[11]; ! 480: ! 481: scsi_free(buffer, 512); ! 482: ! 483: err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_subchnl)); ! 484: if (err) ! 485: return err; ! 486: memcpy_tofs ((void *) arg, &subchnl, sizeof (struct cdrom_subchnl)); ! 487: return result; ! 488: } ! 489: ! 490: case CDROM_GET_UPC: ! 491: { ! 492: struct cdrom_mcn mcn; ! 493: char * buffer; ! 494: ! 495: sr_cmd[0] = SCMD_READ_SUBCHANNEL; ! 496: sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5); ! 497: sr_cmd[2] = 0x40; /* I do want the subchannel info */ ! 498: sr_cmd[3] = 0x02; /* Give me medium catalog number info */ ! 499: sr_cmd[4] = sr_cmd[5] = 0; ! 500: sr_cmd[6] = 0; ! 501: sr_cmd[7] = 0; ! 502: sr_cmd[8] = 24; ! 503: sr_cmd[9] = 0; ! 504: ! 505: buffer = (unsigned char*) scsi_malloc(512); ! 506: if(!buffer) return -ENOMEM; ! 507: ! 508: result = do_ioctl(target, sr_cmd, buffer, 24); ! 509: ! 510: memcpy (mcn.medium_catalog_number, buffer + 9, 13); ! 511: mcn.medium_catalog_number[13] = 0; ! 512: ! 513: scsi_free(buffer, 512); ! 514: ! 515: err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_mcn)); ! 516: if (err) ! 517: return err; ! 518: memcpy_tofs ((void *) arg, &mcn, sizeof (struct cdrom_mcn)); ! 519: return result; ! 520: } ! 521: ! 522: /* these are compatible with the ide-cd driver */ ! 523: case CDROMREADRAW: ! 524: case CDROMREADMODE1: ! 525: case CDROMREADMODE2: ! 526: return -EINVAL; ! 527: ! 528: /* block-copy from ../block/sbpcd.c with some adjustments... */ ! 529: case CDROMMULTISESSION: /* tell start-of-last-session to user */ ! 530: { ! 531: struct cdrom_multisession ms_info; ! 532: long lba; ! 533: ! 534: err = verify_area(VERIFY_READ, (void *) arg, ! 535: sizeof(struct cdrom_multisession)); ! 536: if (err) return (err); ! 537: ! 538: memcpy_fromfs(&ms_info, (void *) arg, sizeof(struct cdrom_multisession)); ! 539: ! 540: if (ms_info.addr_format==CDROM_MSF) { /* MSF-bin requested */ ! 541: lba = scsi_CDs[target].mpcd_sector+CD_BLOCK_OFFSET; ! 542: ms_info.addr.msf.minute = lba / (CD_SECS*CD_FRAMES); ! 543: lba %= CD_SECS*CD_FRAMES; ! 544: ms_info.addr.msf.second = lba / CD_FRAMES; ! 545: ms_info.addr.msf.frame = lba % CD_FRAMES; ! 546: } else if (ms_info.addr_format==CDROM_LBA) /* lba requested */ ! 547: ms_info.addr.lba=scsi_CDs[target].mpcd_sector; ! 548: else return (-EINVAL); ! 549: ! 550: ms_info.xa_flag=scsi_CDs[target].xa_flags & 0x01; ! 551: ! 552: err=verify_area(VERIFY_WRITE,(void *) arg, ! 553: sizeof(struct cdrom_multisession)); ! 554: if (err) return (err); ! 555: ! 556: memcpy_tofs((void *) arg, &ms_info, sizeof(struct cdrom_multisession)); ! 557: return (0); ! 558: } ! 559: ! 560: case BLKRAGET: ! 561: if (!arg) ! 562: return -EINVAL; ! 563: err = verify_area(VERIFY_WRITE, (int *) arg, sizeof(int)); ! 564: if (err) ! 565: return err; ! 566: put_user(read_ahead[MAJOR(inode->i_rdev)], (int *) arg); ! 567: return 0; ! 568: ! 569: case BLKRASET: ! 570: if(!suser()) ! 571: return -EACCES; ! 572: if(!(inode->i_rdev)) ! 573: return -EINVAL; ! 574: if(arg > 0xff) ! 575: return -EINVAL; ! 576: read_ahead[MAJOR(inode->i_rdev)] = arg; ! 577: return 0; ! 578: ! 579: RO_IOCTLS(dev,arg); ! 580: ! 581: case CDROMRESET: ! 582: invalidate_buffers(inode->i_rdev); ! 583: return 0; ! 584: ! 585: default: ! 586: return scsi_ioctl(scsi_CDs[target].device,cmd,(void *) arg); ! 587: } ! 588: } ! 589: ! 590: /* ! 591: * Overrides for Emacs so that we follow Linus's tabbing style. ! 592: * Emacs will notice this stuff at the end of the file and automatically ! 593: * adjust the settings for this buffer only. This must remain at the end ! 594: * of the file. ! 595: * --------------------------------------------------------------------------- ! 596: * Local variables: ! 597: * c-indent-level: 4 ! 598: * c-brace-imaginary-offset: 0 ! 599: * c-brace-offset: -4 ! 600: * c-argdecl-indent: 4 ! 601: * c-label-offset: -4 ! 602: * c-continued-statement-offset: 4 ! 603: * c-continued-brace-offset: 0 ! 604: * indent-tabs-mode: nil ! 605: * tab-width: 8 ! 606: * End: ! 607: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.