|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.