1 /*
2 * libdi - CD Audio Device Interface Library
3 *
4 * Copyright (C) 1993-2004 Ti Kan
5 * E-mail: xmcd@amb.org
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 /*
23 * Toshiba vendor-unique support
24 *
25 * The name "Toshiba" is a trademark of Toshiba Corporation, and is
26 * used here for identification purposes only.
27 */
28 #ifndef lint
29 static char *_vu_tosh_c_ident_ = "@(#)vu_tosh.c 6.40 04/01/14";
30 #endif
31
32 #include "common_d/appenv.h"
33 #include "common_d/util.h"
34 #include "libdi_d/libdi.h"
35 #include "libdi_d/scsipt.h"
36
37 #ifdef VENDOR_TOSHIBA
38
39 extern appdata_t app_data;
40 extern di_client_t *di_clinfo;
41 extern vu_tbl_t scsipt_vutbl[];
42 extern byte_t cdb[];
43 extern di_dev_t *devp;
44
45 STATIC bool_t tosh_audio_muted; /* Is audio muted? */
46
47
48 /*
49 * tosh_playaudio
50 * Play audio function: send vendor-unique play audio command
51 * to the drive.
52 *
53 * Args:
54 * addr_fmt - Flags indicating which address formats are passed in
55 * If ADDR_BLK, then:
56 * start_addr - The logical block starting address
57 * end_addr - The logical block ending address
58 * If ADD_MSF, then:
59 * start_msf - Pointer to the starting MSF address structure
60 * end_msf - Pointer to the ending MSF address structure
61 * If ADDR_TRKIDX, then:
62 * trk - The starting track number
63 * idx - The starting index number
64 * If ADDR_OPTEND, then the ending address, if specified, can be
65 * ignored if possible.
66 *
67 * Return:
68 * TRUE - success
69 * FALSE - failure
70 */
71 /*ARGSUSED*/
72 bool_t
tosh_playaudio(byte_t addr_fmt,sword32_t start_addr,sword32_t end_addr,msf_t * start_msf,msf_t * end_msf,byte_t trk,byte_t idx)73 tosh_playaudio(
74 byte_t addr_fmt,
75 sword32_t start_addr,
76 sword32_t end_addr,
77 msf_t *start_msf,
78 msf_t *end_msf,
79 byte_t trk,
80 byte_t idx
81 )
82 {
83 bool_t ret = FALSE;
84
85 if (!ret && addr_fmt & ADDR_MSF) {
86 /* Position laser head at desired location
87 * and start play.
88 */
89 SCSICDB_RESET(cdb);
90 cdb[0] = OP_VT_AUDSRCH;
91 cdb[1] = 0x01;
92 cdb[2] = (byte_t) util_ltobcd(start_msf->min);
93 cdb[3] = (byte_t) util_ltobcd(start_msf->sec);
94 cdb[4] = (byte_t) util_ltobcd(start_msf->frame);
95 cdb[9] = 0x40;
96
97 ret = pthru_send(devp, DI_ROLE_MAIN, cdb, 10, NULL, 0, NULL, 0,
98 OP_NODATA, 10, TRUE);
99
100 if (ret && !(addr_fmt & ADDR_OPTEND)) {
101 /* Specify end location, muting, and start play */
102 SCSICDB_RESET(cdb);
103 cdb[0] = OP_VT_AUDPLAY;
104 cdb[1] = tosh_audio_muted ? 0x00 : 0x03;
105 cdb[2] = (byte_t) util_ltobcd(end_msf->min);
106 cdb[3] = (byte_t) util_ltobcd(end_msf->sec);
107 cdb[4] = (byte_t) util_ltobcd(end_msf->frame);
108 cdb[9] = 0x40;
109
110 ret = pthru_send(devp, DI_ROLE_MAIN, cdb, 10,
111 NULL, 0, NULL, 0,
112 OP_NODATA, 10, TRUE);
113 }
114 }
115
116 if (!ret && addr_fmt & ADDR_BLK) {
117 /* Position laser head at desired location
118 * and start play.
119 */
120 SCSICDB_RESET(cdb);
121 cdb[0] = OP_VT_AUDSRCH;
122 cdb[1] = 0x01;
123 cdb[2] = ((word32_t) start_addr & 0xff000000) >> 24;
124 cdb[3] = ((word32_t) start_addr & 0x00ff0000) >> 16;
125 cdb[4] = ((word32_t) start_addr & 0x0000ff00) >> 8;
126 cdb[5] = ((word32_t) start_addr & 0x000000ff);
127 cdb[9] = 0x00;
128
129 ret = pthru_send(devp, DI_ROLE_MAIN, cdb, 10, NULL, 0, NULL, 0,
130 OP_NODATA, 10, TRUE);
131
132 if (ret && !(addr_fmt & ADDR_OPTEND)) {
133 /* Specify end location, muting, and start play */
134 SCSICDB_RESET(cdb);
135 cdb[0] = OP_VT_AUDPLAY;
136 cdb[1] = tosh_audio_muted ? 0x00 : 0x03;
137 cdb[2] = ((word32_t) end_addr & 0xff000000) >> 24;
138 cdb[3] = ((word32_t) end_addr & 0x00ff0000) >> 16;
139 cdb[4] = ((word32_t) end_addr & 0x0000ff00) >> 8;
140 cdb[5] = ((word32_t) end_addr & 0x000000ff);
141 cdb[9] = 0x00;
142
143 ret = pthru_send(devp, DI_ROLE_MAIN, cdb, 10,
144 NULL, 0, NULL, 0,
145 OP_NODATA, 10, TRUE);
146 }
147 }
148
149 return (ret);
150 }
151
152
153 /*
154 * tosh_pause_resume
155 * Pause/resume function: send vendor-unique commands to implement
156 * the pause and resume capability.
157 *
158 * Args:
159 * resume - TRUE: resume, FALSE: pause
160 *
161 * Return:
162 * TRUE - success
163 * FALSE - failure
164 */
165 bool_t
tosh_pause_resume(bool_t resume)166 tosh_pause_resume(bool_t resume)
167 {
168 SCSICDB_RESET(cdb);
169
170 if (resume) {
171 cdb[0] = OP_VT_AUDPLAY;
172 cdb[1] = tosh_audio_muted ? 0x00 : 0x03;
173 cdb[9] = 0xc0;
174
175 return (
176 pthru_send(devp, DI_ROLE_MAIN, cdb, 10,
177 NULL, 0, NULL, 0, OP_NODATA, 5, TRUE)
178 );
179 }
180 else {
181 cdb[0] = OP_VT_STILL;
182
183 return (
184 pthru_send(devp, DI_ROLE_MAIN, cdb, 10,
185 NULL, 0, NULL, 0, OP_NODATA, 5, TRUE)
186 );
187 }
188 }
189
190
191 /*
192 * tosh_get_playstatus
193 * Send vendor-unique command to obtain current audio playback
194 * status.
195 *
196 * Args:
197 * sp - Pointer to the caller-supplied cdstat_t return structure
198 *
199 * Return:
200 * TRUE - success
201 * FALSE - failure
202 */
203 bool_t
tosh_get_playstatus(cdstat_t * sp)204 tosh_get_playstatus(cdstat_t *sp)
205 {
206 byte_t buf[sizeof(tsubq_data_t)];
207 tsubq_data_t *d;
208
209
210 (void) memset(buf, 0, sizeof(buf));
211
212 SCSICDB_RESET(cdb);
213 cdb[0] = OP_VT_RDSUBQ;
214 cdb[1] = SZ_VT_RDSUBQ & 0x1f;
215
216 if (!pthru_send(devp, DI_ROLE_MAIN, cdb, 10, buf, SZ_VT_RDSUBQ,
217 NULL, 0, OP_DATAIN, 5, TRUE))
218 return FALSE;
219
220 DBGDUMP(DBG_DEVIO)("tosh: Read Subchannel data bytes",
221 buf, SZ_VT_RDSUBQ);
222
223 d = (tsubq_data_t *)(void *) buf;
224
225 sp->track = (int) util_bcdtol((word32_t) d->trkno);
226 sp->index = (int) util_bcdtol((word32_t) d->idxno);
227
228 sp->abs_addr.min = (byte_t) util_bcdtol(d->abs_min);
229 sp->abs_addr.sec = (byte_t) util_bcdtol(d->abs_sec);
230 sp->abs_addr.frame = (byte_t) util_bcdtol(d->abs_frame);
231 sp->rel_addr.min = (byte_t) util_bcdtol(d->rel_min);
232 sp->rel_addr.sec = (byte_t) util_bcdtol(d->rel_sec);
233 sp->rel_addr.frame = (byte_t) util_bcdtol(d->rel_frame);
234 util_msftoblk(
235 sp->abs_addr.min, sp->abs_addr.sec, sp->abs_addr.frame,
236 &sp->abs_addr.addr, MSF_OFFSET
237 );
238 util_msftoblk(
239 sp->rel_addr.min, sp->rel_addr.sec, sp->rel_addr.frame,
240 &sp->rel_addr.addr, 0
241 );
242
243 /* Translate Toshiba audio status to SCSI-2 audio status */
244 switch (d->audio_status) {
245 case TAUD_PLAYING:
246 sp->status = CDSTAT_PLAYING;
247 break;
248
249 case TAUD_SRCH_PAUSED:
250 case TAUD_PAUSED:
251 sp->status = CDSTAT_PAUSED;
252 break;
253
254 case TAUD_OTHER:
255 sp->status = CDSTAT_COMPLETED;
256 break;
257 }
258
259 return TRUE;
260 }
261
262
263 /*
264 * tosh_get_toc
265 * Send vendor-unique command to obtain the disc table-of-contents
266 *
267 * Args:
268 * s - Pointer to the curstat_t structure, which contains the TOC
269 * table to be updated.
270 *
271 * Return:
272 * TRUE - success
273 * FALSE - failure
274 */
275 bool_t
tosh_get_toc(curstat_t * s)276 tosh_get_toc(curstat_t *s)
277 {
278 int i,
279 j;
280 byte_t buf[SZ_VT_RDINFO];
281 tinfo_00_t *t0;
282 tinfo_01_t *t1;
283 tinfo_02_t *t2;
284
285
286 (void) memset(buf, 0, sizeof(buf));
287
288 /* Find number of tracks */
289 SCSICDB_RESET(cdb);
290 cdb[0] = OP_VT_RDINFO;
291 cdb[1] = 0x00;
292
293 if (!pthru_send(devp, DI_ROLE_MAIN, cdb, 10, buf, SZ_VT_RDINFO,
294 NULL, 0, OP_DATAIN, 5, TRUE))
295 return FALSE;
296
297 DBGDUMP(DBG_DEVIO)("tosh: Read Disc Info data bytes",
298 buf, SZ_VT_RDINFO);
299
300 t0 = (tinfo_00_t *) buf;
301 s->first_trk = (byte_t) util_bcdtol(t0->first_trk);
302 s->last_trk = (byte_t) util_bcdtol(t0->last_trk);
303
304 /* Get the starting position of each track */
305 for (i = 0, j = (int) s->first_trk; j <= (int) s->last_trk; i++, j++) {
306 (void) memset(buf, 0, sizeof(buf));
307
308 SCSICDB_RESET(cdb);
309 cdb[0] = OP_VT_RDINFO;
310 cdb[1] = 0x02;
311 cdb[2] = (byte_t) util_ltobcd(j);
312
313 if (!pthru_send(devp, DI_ROLE_MAIN, cdb, 10,
314 buf, SZ_VT_RDINFO, NULL, 0,
315 OP_DATAIN, 5, TRUE))
316 return FALSE;
317
318 DBGDUMP(DBG_DEVIO)("tosh: Read Disc Info data bytes",
319 buf, SZ_VT_RDINFO);
320
321 t2 = (tinfo_02_t *) buf;
322
323 s->trkinfo[i].trkno = j;
324 s->trkinfo[i].min = (byte_t) util_bcdtol(t2->min);
325 s->trkinfo[i].sec = (byte_t) util_bcdtol(t2->sec);
326 s->trkinfo[i].frame = (byte_t) util_bcdtol(t2->frame);
327 util_msftoblk(
328 s->trkinfo[i].min,
329 s->trkinfo[i].sec,
330 s->trkinfo[i].frame,
331 &s->trkinfo[i].addr,
332 MSF_OFFSET
333 );
334 }
335 s->tot_trks = (byte_t) i;
336
337 (void) memset(buf, 0, sizeof(buf));
338
339 /* Get the lead out track position */
340 SCSICDB_RESET(cdb);
341 cdb[0] = OP_VT_RDINFO;
342 cdb[1] = 0x01;
343
344 if (!pthru_send(devp, DI_ROLE_MAIN, cdb, 10, buf, SZ_VT_RDINFO,
345 NULL, 0, OP_DATAIN, 5, TRUE))
346 return FALSE;
347
348 DBGDUMP(DBG_DEVIO)("tosh: Read Disc Info data bytes",
349 buf, SZ_VT_RDINFO);
350
351 t1 = (tinfo_01_t *) buf;
352
353 s->trkinfo[i].trkno = LEAD_OUT_TRACK;
354 s->discpos_tot.min = s->trkinfo[i].min = (byte_t) util_bcdtol(t1->min);
355 s->discpos_tot.sec = s->trkinfo[i].sec = (byte_t) util_bcdtol(t1->sec);
356 s->discpos_tot.frame = s->trkinfo[i].frame =
357 (byte_t) util_bcdtol(t1->frame);
358 util_msftoblk(
359 s->trkinfo[i].min,
360 s->trkinfo[i].sec,
361 s->trkinfo[i].frame,
362 &s->trkinfo[i].addr,
363 MSF_OFFSET
364 );
365 s->discpos_tot.addr = s->trkinfo[i].addr;
366
367 return TRUE;
368 }
369
370
371 /*
372 * tosh_mute
373 * Send vendor-unique command to mute/unmute the audio
374 *
375 * Args:
376 * mute - TRUE: mute audio, FALSE: unmute audio
377 *
378 * Return:
379 * TRUE - success
380 * FALSE - failure
381 */
382 bool_t
tosh_mute(bool_t mute)383 tosh_mute(bool_t mute)
384 {
385 curstat_t *s = di_clinfo->curstat_addr();
386
387 if (tosh_audio_muted != mute) {
388 switch (s->mode) {
389 case MOD_BUSY:
390 case MOD_NODISC:
391 case MOD_STOP:
392 case MOD_PAUSE:
393 break;
394
395 default:
396 SCSICDB_RESET(cdb);
397 cdb[0] = OP_VT_AUDPLAY;
398 cdb[1] = mute ? 0x00 : 0x03;
399 cdb[9] = 0xc0;
400
401 if (!pthru_send(devp, DI_ROLE_MAIN, cdb, 10,
402 NULL, 0, NULL, 0, OP_NODATA, 5, TRUE))
403 return FALSE;
404 break;
405 }
406
407 tosh_audio_muted = mute;
408 }
409
410 return TRUE;
411 }
412
413
414 /*
415 * tosh_eject
416 * Send vendor-unique command to eject the caddy
417 *
418 * Args:
419 * Nothing.
420 *
421 * Return:
422 * TRUE - success
423 * FALSE - failure
424 */
425 bool_t
tosh_eject(void)426 tosh_eject(void)
427 {
428 SCSICDB_RESET(cdb);
429 cdb[0] = OP_VT_EJECT;
430 cdb[1] = 0x01; /* Set immediate bit */
431
432 return (pthru_send(devp, DI_ROLE_MAIN, cdb, 10, NULL, 0, NULL, 0,
433 OP_NODATA, 20, TRUE));
434 }
435
436
437 /*
438 * tosh_init
439 * Initialize the vendor-unique support module
440 *
441 * Args:
442 * Nothing.
443 *
444 * Return:
445 * Nothing.
446 */
447 void
tosh_init(void)448 tosh_init(void)
449 {
450 /* Register vendor_unique module entry points */
451 scsipt_vutbl[VENDOR_TOSHIBA].vendor = "Toshiba";
452 scsipt_vutbl[VENDOR_TOSHIBA].playaudio = tosh_playaudio;
453 scsipt_vutbl[VENDOR_TOSHIBA].pause_resume = tosh_pause_resume;
454 scsipt_vutbl[VENDOR_TOSHIBA].start_stop = NULL;
455 scsipt_vutbl[VENDOR_TOSHIBA].get_playstatus = tosh_get_playstatus;
456 scsipt_vutbl[VENDOR_TOSHIBA].volume = NULL;
457 scsipt_vutbl[VENDOR_TOSHIBA].route = NULL;
458 scsipt_vutbl[VENDOR_TOSHIBA].mute = tosh_mute;
459 scsipt_vutbl[VENDOR_TOSHIBA].get_toc = tosh_get_toc;
460 scsipt_vutbl[VENDOR_TOSHIBA].eject = tosh_eject;
461 scsipt_vutbl[VENDOR_TOSHIBA].start = NULL;
462 scsipt_vutbl[VENDOR_TOSHIBA].halt = NULL;
463 }
464
465
466 #endif /* VENDOR_TOSHIBA */
467
468