Annotation of Gnu-Mach/i386/i386at/gpl/linux/scsi/sr_ioctl.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.