Annotation of Examples/UNIX/SCSI_CD/cd_commands.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * cd_commands.c: CD-ROM drive specific commands
        !             3:  * NOTE: this version is taylored for audio. Basically it uses msf address
        !             4:  *       format
        !             5:  *
        !             6:  * History
        !             7:  * -------
        !             8:  * Mon Sep 16 15:57:35 PDT 1991 James C. Lee at NeXT
        !             9:  *  Created
        !            10:  */
        !            11: 
        !            12: #import "cd_commands.h"
        !            13: #import "scsi_commands.h"
        !            14: #import "myflags.h"
        !            15: #import <libc.h>
        !            16: #import <objc/objc.h>
        !            17: #import <c.h>
        !            18: 
        !            19: int    do_eject(int fd, struct timeval *tvp, struct esense_reply *erp)
        !            20: {
        !            21:        struct scsi_req sr;
        !            22:        struct start_stop_cmd *sscp;
        !            23:        int err;
        !            24: 
        !            25:        bzero((char *)&sr, sizeof(sr));
        !            26: 
        !            27:        sscp = (struct start_stop_cmd *)&sr.sr_cdb;
        !            28:        sscp->ssc_opcode = C6OP_STARTSTOP;
        !            29:        sscp->ssc_imm = 0;      /* status will be returned after the operation is
        !            30:                                                   completed */
        !            31:        sscp->ssc_loej = 1;     /* eject when spin down (scc_start=0) */
        !            32:        sscp->ssc_start = 0;    /* spin down */
        !            33: 
        !            34:        sr.sr_addr = NULL;
        !            35:        sr.sr_dma_max = 0;      /* don't really do I/O to memory */
        !            36:        sr.sr_ioto = 10;        /* time out in 10 seconds */
        !            37:        sr.sr_dma_dir = SR_DMA_RD;
        !            38: 
        !            39:        err = ioctl(fd, SDIOCSRQ, &sr);
        !            40: 
        !            41:        *tvp = sr.sr_exec_time;
        !            42: 
        !            43:        if (sr.sr_dma_xfr != 0)
        !            44:                fatal("scsi driver did transfer: %d", sr.sr_dma_xfr);
        !            45: 
        !            46:        *erp = sr.sr_esense;
        !            47:        return err | sr.sr_io_status;
        !            48: }
        !            49: 
        !            50: /* same command as do_eject except that sscp->ssc_start=1, and
        !            51:    sscp->ssc_loej=0 */
        !            52: int    do_spinup(int fd, struct timeval *tvp, struct esense_reply *erp)
        !            53: {
        !            54:        struct scsi_req sr;
        !            55:        struct start_stop_cmd *sscp;
        !            56:        int err;
        !            57: 
        !            58:        bzero((char *)&sr, sizeof(sr));
        !            59: 
        !            60:        sscp = (struct start_stop_cmd *)&sr.sr_cdb;
        !            61:        sscp->ssc_opcode = C6OP_STARTSTOP;
        !            62:        sscp->ssc_imm = 0;      /* status will be returned after the operation is
        !            63:                                                   completed */
        !            64:        sscp->ssc_loej = 0;
        !            65:        sscp->ssc_start = 1;    /* spin up */
        !            66: 
        !            67:        sr.sr_addr = NULL;
        !            68:        sr.sr_dma_max = 0;      /* don't really do I/O to memory */
        !            69:        sr.sr_ioto = 10;        /* time out in 10 seconds */
        !            70:        sr.sr_dma_dir = SR_DMA_RD;
        !            71: 
        !            72:        err = ioctl(fd, SDIOCSRQ, &sr);
        !            73: 
        !            74:        *tvp = sr.sr_exec_time;
        !            75: 
        !            76:        if (sr.sr_dma_xfr != 0)
        !            77:                fatal("scsi driver did transfer: %d", sr.sr_dma_xfr);
        !            78: 
        !            79:        *erp = sr.sr_esense;
        !            80:        return err | sr.sr_io_status;
        !            81: }
        !            82: 
        !            83: /* read table of content */
        !            84: int do_readtoc(int fd, int track, struct toc10_reply *tocrp,
        !            85:        struct esense_reply *erp)
        !            86: {
        !            87:        struct scsi_req sr;
        !            88:        struct readtoc10_cmd *rt10cp;
        !            89:        int err;
        !            90: 
        !            91:        bzero((char *)&sr, sizeof(sr));
        !            92: 
        !            93:        rt10cp = (struct readtoc10_cmd *)&sr.sr_cdb;
        !            94:        rt10cp->rt10_op_code = C10OP_READTOC;
        !            95:        rt10cp->rt10_msf = 0;   /* don't use msf format */
        !            96:        rt10cp->rt10_starttrack = track;
        !            97:        /* read only info on one track */
        !            98:        rt10cp->rt10_length = sizeof(struct toc10_reply);
        !            99:        
        !           100:        sr.sr_addr = (char *) tocrp;
        !           101:        sr.sr_dma_max = sizeof(*tocrp);
        !           102:        sr.sr_ioto = 5;         /* time out in 5 seconds */
        !           103:        sr.sr_dma_dir = SR_DMA_RD;
        !           104: 
        !           105:        err = ioctl(fd, SDIOCSRQ, &sr);
        !           106: 
        !           107:        *erp = sr.sr_esense;
        !           108:        return err | sr.sr_io_status;
        !           109: }
        !           110: 
        !           111: /* read entire table of contents */
        !           112: int do_readtoc_all(int fd, struct toc_all *toc_all, struct esense_reply *erp)
        !           113: {
        !           114:        struct scsi_req sr;
        !           115:        struct readtoc10_cmd *rt10cp;
        !           116:        struct toc10_reply tocr;
        !           117:        int             err;
        !           118:        char    *toc_reply;     /* toc reply from scsi bus, need to be allocated */
        !           119:        u_int   toc_data_length;
        !           120:        struct rtr10_desc       *desc;  /* pointer to trverse through *toc_reply */
        !           121:        int             nrecords,       /* number of desc blocks info in toc */
        !           122:                        i, track;
        !           123: 
        !           124:        bzero((char *)&sr, sizeof(sr));
        !           125: 
        !           126:        rt10cp = (struct readtoc10_cmd *)&sr.sr_cdb;
        !           127:        rt10cp->rt10_op_code = C10OP_READTOC;
        !           128:        rt10cp->rt10_msf = 0;   /* don't use msf format */
        !           129:        rt10cp->rt10_starttrack = 0;
        !           130:        /* read only info on track 0 to find out TOC data length */
        !           131:        rt10cp->rt10_length = sizeof(struct toc10_reply);
        !           132:        
        !           133:        sr.sr_addr = (char *) &tocr;
        !           134:        sr.sr_dma_max = sizeof(tocr);
        !           135:        sr.sr_ioto = 5;         /* time out in 5 seconds */
        !           136:        sr.sr_dma_dir = SR_DMA_RD;
        !           137: 
        !           138:        err = ioctl(fd, SDIOCSRQ, &sr);
        !           139:        *erp = sr.sr_esense;
        !           140:        if (err | sr.sr_io_status) {    /* problem reading TOC, return */
        !           141:                return err | sr.sr_io_status;
        !           142:        }
        !           143:        
        !           144:        /* record first & last track, and toc data length */
        !           145:        toc_all->firsttrack = tocr.h.rtr_firsttrack;
        !           146:        toc_all->lasttrack = tocr.h.rtr_lasttrack;
        !           147:        toc_data_length = tocr.h.rtr_datalength;
        !           148:        nrecords = toc_data_length / sizeof(struct rtr10_desc);
        !           149: 
        !           150:        /* prepare for second read toc for the whole thing */
        !           151:        bzero((char *)&sr, sizeof(sr));
        !           152: 
        !           153:        rt10cp = (struct readtoc10_cmd *)&sr.sr_cdb;
        !           154:        rt10cp->rt10_op_code = C10OP_READTOC;
        !           155:        rt10cp->rt10_msf = 1;   /* want msf format */
        !           156:        rt10cp->rt10_starttrack = 0;
        !           157:        /* read only info on track 0 to find out TOC data length */
        !           158:        rt10cp->rt10_length = toc_data_length + sizeof(struct rtr_header);
        !           159: 
        !           160:        toc_reply = (char *) malloc(toc_data_length + sizeof(struct rtr_header));
        !           161:        sr.sr_addr = toc_reply;
        !           162:        sr.sr_dma_max = toc_data_length + sizeof(struct rtr_header);
        !           163:        sr.sr_ioto = 5;         /* time out in 5 seconds */
        !           164:        sr.sr_dma_dir = SR_DMA_RD;
        !           165:        
        !           166:        err = ioctl(fd, SDIOCSRQ, &sr);
        !           167:        *erp = sr.sr_esense;
        !           168:        if (err | sr.sr_io_status) {    /* problem reading TOC, return */
        !           169:                return err | sr.sr_io_status;
        !           170:        }
        !           171:        
        !           172:        /* successfully read the whole thing, now process it */
        !           173:        toc_all->naudio = toc_all->ndata = 0;   /* zero counts */
        !           174:        for (i=0; i<=100; i++) {        /* first initialize addr to be invalid */
        !           175:                toc_all->info[i].hour = -1;
        !           176:                toc_all->info[i].min = -1;
        !           177:                toc_all->info[i].sec = -1;
        !           178:                toc_all->info[i].frame = -1;
        !           179:        }
        !           180:        desc = (struct rtr10_desc *) &(toc_reply[4]);   /* skip the header */
        !           181:        for (i=0; i<nrecords; i++) {
        !           182:                track = desc->t10d_track;
        !           183:                if (track == 0xaa) track = 100; /* transition area */
        !           184:                if (desc->t10d_control & DATA_TRACK)
        !           185:                        toc_all->ndata++;
        !           186:                else if (track != 100)
        !           187:                        toc_all->naudio++;
        !           188:                toc_all->info[track].control = desc->t10d_control;
        !           189:                toc_all->info[track].hour = desc->t10d_hour;
        !           190:                toc_all->info[track].min = desc->t10d_min;
        !           191:                toc_all->info[track].sec = desc->t10d_sec;
        !           192:                toc_all->info[track].frame = desc->t10d_frame;
        !           193:                desc++;
        !           194:        }
        !           195: #ifdef CD_DEBUG
        !           196:        /* print the table of contents to stderr */
        !           197:        for (i=toc_all->firsttrack; i<=toc_all->lasttrack; i++) {
        !           198:                printf("Track %2d: %d:%d:%d:%d %c\n", i,
        !           199:                        toc_all->info[i].hour, toc_all->info[i].min, toc_all->info[i].sec,
        !           200:                        toc_all->info[i].frame,
        !           201:                        toc_all->info[i].control&DATA_TRACK? 'D' : 'A');
        !           202:        }
        !           203:                printf("Track LO: %d:%d:%d:%d %c\n",
        !           204:                        toc_all->info[100].hour, toc_all->info[100].min,
        !           205:                        toc_all->info[100].sec, toc_all->info[100].frame,
        !           206:                toc_all->info[100].control&DATA_TRACK? 'D' : 'A');
        !           207: #endif
        !           208:        return err | sr.sr_io_status;
        !           209: }
        !           210: 
        !           211: /* play audio (C6OP_PLAYAUDIO = c8h) */
        !           212: int do_playaudio(int fd, int lba, int length, struct esense_reply *erp)
        !           213: {
        !           214:        struct scsi_req sr;
        !           215:        struct playaudio_cmd *pap;
        !           216:        int err;
        !           217: 
        !           218:        bzero((char *)&sr, sizeof(sr));
        !           219: 
        !           220:        pap = (struct playaudio_cmd *)&sr.sr_cdb;
        !           221:        pap->pa_op_code = C6OP_PLAYAUDIO;
        !           222:        pap->pa_lba = lba;      /* block to play audio from */
        !           223:        pap->pa_length = length;
        !           224:        
        !           225:        sr.sr_addr = NULL;
        !           226:        sr.sr_dma_max = 0;
        !           227:        sr.sr_ioto = 10;                /* time out in 10 seconds */
        !           228:        sr.sr_dma_dir = SR_DMA_RD;
        !           229: 
        !           230:        err = ioctl(fd, SDIOCSRQ, &sr);
        !           231: 
        !           232:        if (sr.sr_dma_xfr != 0)
        !           233:                fatal("scsi driver did transfer: %d", sr.sr_dma_xfr);
        !           234: 
        !           235:        *erp = sr.sr_esense;
        !           236:        return err | sr.sr_io_status;
        !           237: }
        !           238: 
        !           239: /* pause audio (C10OP_PAUSE = c5h) */
        !           240: int do_pauseaudio(int fd, int pause, struct esense_reply *erp)
        !           241: {
        !           242:        struct scsi_req sr;
        !           243:        struct pause_cmd *pp;
        !           244:        int err;
        !           245: 
        !           246:        bzero((char *)&sr, sizeof(sr));
        !           247: 
        !           248:        pp = (struct pause_cmd *)&sr.sr_cdb;
        !           249:        pp->p_op_code = C10OP_PAUSE;
        !           250:        pp->p_pause = pause;
        !           251:        
        !           252:        sr.sr_addr = NULL;
        !           253:        sr.sr_dma_max = 0;
        !           254:        sr.sr_ioto = 5;         /* time out in 5 seconds */
        !           255:        sr.sr_dma_dir = SR_DMA_RD;
        !           256: 
        !           257:        err = ioctl(fd, SDIOCSRQ, &sr);
        !           258: 
        !           259:        if (sr.sr_dma_xfr != 0)
        !           260:                fatal("scsi driver did transfer: %d", sr.sr_dma_xfr);
        !           261: 
        !           262:        *erp = sr.sr_esense;
        !           263:        return err | sr.sr_io_status;
        !           264: }
        !           265: 
        !           266: /* play audio (C10OP_PLAYAUDIO_MSF = 47h) */
        !           267: int do_playaudio_msf(int fd, struct msf startmsf, struct msf endmsf,
        !           268:        struct esense_reply *erp)
        !           269: {
        !           270:        struct scsi_req sr;
        !           271:        struct playaudio_msf_cmd *pap;
        !           272:        int err;
        !           273: 
        !           274:        bzero((char *)&sr, sizeof(sr));
        !           275: 
        !           276:        pap = (struct playaudio_msf_cmd *)&sr.sr_cdb;
        !           277:        pap->pam_op_code = C10OP_PLAYAUDIO_MSF;
        !           278:        pap->pam_start_min = startmsf.min;
        !           279:        pap->pam_start_sec = startmsf.sec;
        !           280:        pap->pam_start_frame = startmsf.frame;
        !           281:        pap->pam_end_min = endmsf.min;
        !           282:        pap->pam_end_sec = endmsf.sec;
        !           283:        pap->pam_end_frame = endmsf.frame;
        !           284:        
        !           285:        sr.sr_addr = NULL;
        !           286:        sr.sr_dma_max = 0;
        !           287:        sr.sr_ioto = 10;                /* time out in 10 seconds */
        !           288:        sr.sr_dma_dir = SR_DMA_RD;
        !           289: 
        !           290:        err = ioctl(fd, SDIOCSRQ, &sr);
        !           291: 
        !           292:        if (sr.sr_dma_xfr != 0)
        !           293:                fatal("scsi driver did transfer: %d", sr.sr_dma_xfr);
        !           294: 
        !           295:        *erp = sr.sr_esense;
        !           296:        return err | sr.sr_io_status;
        !           297: }
        !           298: 
        !           299: /* read sub-channel data (C10OP_READSUBHCANNEL = 42h) */
        !           300: int    do_readsubchannel(int fd, int msf, int subq, int page, int track,
        !           301:        struct sc_reply *scrp, struct esense_reply *erp)
        !           302: {
        !           303:        struct scsi_req sr;
        !           304:        struct readsc_cmd *rscp;
        !           305:        int err;
        !           306:        int     i;
        !           307:        char *cptr;
        !           308: 
        !           309:        bzero((char *)&sr, sizeof(sr));
        !           310:        
        !           311:        rscp = (struct readsc_cmd *) &sr.sr_cdb;
        !           312:        rscp->rsc_op_code = C10OP_READSUBHCANNEL;
        !           313:        rscp->rsc_msf = msf;
        !           314:        rscp->rsc_subq = subq;
        !           315:        rscp->rsc_dformat = page;
        !           316:        rscp->rsc_track = track;
        !           317:        rscp->rsc_length = sizeof(struct sc_reply);
        !           318:        
        !           319:        cptr = (char *) rscp;
        !           320: /*     printf("Cmd: ");
        !           321:        for (i=0; i<10; i++) {
        !           322:                printf("%.2x ", *cptr++);
        !           323:        }
        !           324:        printf("\n");*/
        !           325:        
        !           326:        sr.sr_addr = (char *) scrp;
        !           327:        sr.sr_dma_max = sizeof(struct sc_reply);
        !           328:        sr.sr_ioto = 5;         /* time out in 5 seconds */
        !           329:        sr.sr_dma_dir = SR_DMA_RD;
        !           330: 
        !           331:        err = ioctl(fd, SDIOCSRQ, &sr);
        !           332:        *erp = sr.sr_esense;
        !           333:        return err | sr.sr_io_status;
        !           334: }
        !           335: 
        !           336: /* get playback status data (C10OP_PLAYBACKSTATUS = c4h) */
        !           337: int    do_playbackstatus(int fd, struct playback_data *pbdatap,
        !           338:        struct esense_reply *erp)
        !           339: {
        !           340:        struct scsi_req sr;
        !           341:        struct playback_cmd *pbcp;
        !           342:        int err;
        !           343: 
        !           344:        bzero((char *)&sr, sizeof(sr));
        !           345:        
        !           346:        pbcp = (struct playback_cmd *) &sr.sr_cdb;
        !           347:        pbcp->pb_opcode = C10OP_PLAYBACKSTATUS;
        !           348:        pbcp->pb_length = sizeof(struct playback_data);
        !           349:                
        !           350:        sr.sr_addr = (char *) pbdatap;
        !           351:        sr.sr_dma_max = sizeof(struct playback_data);
        !           352:        sr.sr_ioto = 1;         /* time out in 1 second */
        !           353:        sr.sr_dma_dir = SR_DMA_RD;
        !           354: 
        !           355:        err = ioctl(fd, SDIOCSRQ, &sr);
        !           356:        *erp = sr.sr_esense;
        !           357:        return err | sr.sr_io_status;
        !           358: }
        !           359: 
        !           360: 
        !           361: /* playback status control (C10OP_PLAYBACKCONTROL = c9h) */
        !           362: int    do_playbackcontrol(int fd, struct playback_data *pbdatap,
        !           363:        struct esense_reply *erp)
        !           364: {
        !           365:        struct scsi_req sr;
        !           366:        struct playback_cmd *pbcp;
        !           367:        int err;
        !           368: 
        !           369:        bzero((char *)&sr, sizeof(sr));
        !           370:        
        !           371:        pbcp = (struct playback_cmd *) &sr.sr_cdb;
        !           372:        pbcp->pb_opcode = C10OP_PLAYBACKCONTROL;
        !           373:        pbcp->pb_length = sizeof(struct playback_data);
        !           374:                
        !           375:        sr.sr_addr = (char *) pbdatap;
        !           376:        sr.sr_dma_max = sizeof(struct playback_data);
        !           377:        sr.sr_ioto = 1;         /* time out in 1 second */
        !           378:        sr.sr_dma_dir = SR_DMA_WR;
        !           379: 
        !           380:        err = ioctl(fd, SDIOCSRQ, &sr);
        !           381:        *erp = sr.sr_esense;
        !           382:        return err | sr.sr_io_status;
        !           383: }
        !           384: 
        !           385: /* print sub-channel data */
        !           386: void printf_sc(int page, struct sc_reply *scrp)
        !           387: {
        !           388:        struct msf      *msfp;  /* msf structure */
        !           389:        int                     i;
        !           390:        
        !           391:        printf("Audio status: %.2x, Page %d\n", scrp->scr_header.sch_astatus,
        !           392:                page);
        !           393:        switch (page) {
        !           394:                case 1: /* page 1 */
        !           395:                        printf("Track       : %d\n", scrp->u.u_scr_cur_pos.sc1_track);
        !           396:                        printf("Index       : %d\n", scrp->u.u_scr_cur_pos.sc1_index);
        !           397:                        msfp = (struct msf *) &(scrp->u.u_scr_cur_pos.sc1_abs_addr);
        !           398:                        printf("Abs Address : %d:%d:%d:%d\n", msfp->hour, msfp->min,
        !           399:                                msfp->sec, msfp->frame);
        !           400:                        msfp = (struct msf *) &(scrp->u.u_scr_cur_pos.sc1_rel_addr);
        !           401:                        printf("Rel Address : %d:%d:%d:%d\n", msfp->hour, msfp->min,
        !           402:                                msfp->sec, msfp->frame);
        !           403:                        break;
        !           404:                case 2: /* page 2 */
        !           405:                        printf("MCVal       : %d\n", scrp->u.u_scr_med_cat.sc2_mcval);
        !           406:                        printf("MCatalog    : ");
        !           407:                        for (i=0; i<15; i++) {
        !           408:                                printf("%.2x", scrp->u.u_scr_med_cat.sc2_med_cat[i]);
        !           409:                        }
        !           410:                        printf("\n");
        !           411:                        break;
        !           412:                case 3: /* page 3 */
        !           413:                        /* don't need to use it now */
        !           414:                        printf("Page 3 not currently implemented\n");
        !           415:                        break;
        !           416:                default:
        !           417:                        printf("Unknown page number %d\n", page);
        !           418:                        break;
        !           419:        }
        !           420:        return;
        !           421: }
        !           422: 
        !           423: 
        !           424: /* print playback status data */
        !           425: void printf_pb(struct playback_data *pbdatap)
        !           426: {
        !           427:        printf("pbd_ch0_sel: 0x%x\n", pbdatap->pbd_ch0_sel);
        !           428:        printf("pbd_ch0_vol: 0x%x\n", pbdatap->pbd_ch0_vol);
        !           429:        printf("pbd_ch1_sel: 0x%x\n", pbdatap->pbd_ch1_sel);
        !           430:        printf("pbd_ch1_vol: 0x%x\n", pbdatap->pbd_ch1_vol);
        !           431:        printf("pbd_ch2_sel: 0x%x\n", pbdatap->pbd_ch2_sel);
        !           432:        printf("pbd_ch2_vol: 0x%x\n", pbdatap->pbd_ch2_vol);
        !           433:        printf("pbd_ch3_sel: 0x%x\n", pbdatap->pbd_ch3_sel);
        !           434:        printf("pbd_ch3_vol: 0x%x\n", pbdatap->pbd_ch3_vol);
        !           435:        return;
        !           436: }

unix.superglobalmegacorp.com

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