Annotation of Examples/UNIX/SCSI_CD/cd_commands.c, revision 1.1.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.