|
|
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.