|
|
1.1 root 1: /*
2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22:
23: #include <IOKit/IOLib.h>
24: #include <IOKit/IOReturn.h>
25: #include <IOKit/IOMemoryDescriptor.h>
26: #include <IOKit/scsi/IOSCSIDeviceInterface.h>
27: #include <IOKit/storage/scsi/IOSCSICDDrive.h>
28: #include <IOKit/storage/scsi/IOSCSICDDriveNub.h>
29:
30: /* Device types that we intend to handle. */
31:
32: const UInt8 DT_CDROM = 0x05; /* CD-ROM */
33:
34: #define super IOSCSIHDDrive
35: OSDefineMetaClassAndStructors(IOSCSICDDrive,IOSCSIHDDrive)
36:
37: IOReturn
38: IOSCSICDDrive::audioPlay(positioningType addressType,cdAddress address,audioPlayMode mode)
39: {
40: return(doAudioPlayCommand(addressType,address,
41: _audioStopAddress.type,_audioStopAddress.address));
42: }
43:
44: IOReturn
45: IOSCSICDDrive::audioPause(bool pause)
46: {
47: //xxxx
48: return(kIOReturnUnsupported);
49: }
50:
51: IOReturn
52: IOSCSICDDrive::audioScan(positioningType addressType,cdAddress address,bool reverse)
53: {
54: struct context *cx;
55: struct IOAudioScancdb *c;
56: IOSCSICommand *req;
57: SCSICDBInfo scsiCDB;
58: IOReturn result;
59:
60: cx = allocateContext();
61: if (cx == NULL) {
62: return(kIOReturnNoMemory);
63: }
64:
65: req = cx->scsireq;
66:
67: bzero( &scsiCDB, sizeof(scsiCDB) );
68:
69: c = (struct IOAudioScancdb *)&scsiCDB.cdb;
70:
71: c->opcode = SOP_AUDIOSCAN;
72: c->lunbits = 0;
73: if (!reverse) {
74: c->lunbits |= IOAudioScancdb::kForward;
75: }
76:
77: switch (addressType) {
78:
79: case kBlockAddress :
80: c->start3 = address >> 24;
81: c->start2 = address >> 16;
82: c->start1 = address >> 8;
83: c->start0 = address & 0xff;
84: c->ctlbyte = IOAudioScancdb::kType_lba;
85: break;
86:
87: case kAbsoluteTime :
88: c->start3 = address >> 24;
89: c->start2 = address >> 16;
90: c->start1 = address >> 8;
91: c->start0 = address & 0xff;
92: c->ctlbyte = IOAudioScancdb::kType_msf;
93: break;
94:
95: case kTrackNumber :
96: c->start3 = 0;
97: c->start2 = 0;
98: c->start1 = 0;
99: c->start0 = address & 0xff;
100: c->ctlbyte = IOAudioScancdb::kType_track;
101: break;
102:
103: default :
104: deleteContext(cx);
105: return(kIOReturnBadArgument);
106: };
107:
108: scsiCDB.cdbLength = 6;
109: scsiCDB.cdbFlags = 0;
110: req->setCDB( &scsiCDB );
111: req->setPointers(cx->senseDataDesc, 255, false, true);
112: req->setPointers( cx->memory, 0, false );
113: req->setTimeout(1 * 1000);
114:
115: result = simpleSynchIO(cx);
116:
117: deleteContext(cx);
118:
119: return(result);
120: }
121:
122: IOReturn
123: IOSCSICDDrive::audioTrackSearch(positioningType addressType,cdAddress address,
124: bool startPlay,audioPlayMode mode)
125: {
126: IOReturn result;
127: UInt32 lba;
128:
129: result = convertMSFToLba(&lba,address);
130: if (result != kIOReturnSuccess) {
131: return(result);
132: }
133:
134: result = seek(lba);
135: if (result != kIOReturnSuccess) {
136: return(result);
137: }
138:
139: if (startPlay) {
140: return(audioPlay(addressType,address,mode));
141: } else {
142: return(result);
143: }
144: }
145:
146: IOReturn
147: IOSCSICDDrive::convertMSFToLba(UInt32 *lba,cdAddress address)
148: {
149: //xxx wrong! incoming msf values are bcd!
150: *lba = ((address >> 16) * 75 * 60) + /* min */
151: ((address >> 8) * 75) + /* sec */
152: (address & 0xff); /* frames */
153:
154: return(kIOReturnSuccess);
155: }
156:
157: bool
158: IOSCSICDDrive::deviceTypeMatches(UInt8 inqBuf[],UInt32 inqLen)
159: {
160: if ((inqBuf[0] & 0x1f) == DT_CDROM) {
161: // IOLog("%s[IOSCSICDDrive]::deviceTypeMatches, returning TRUE\n",getName());
162: return(true);
163: } else {
164: // IOLog("%s[IOSCSICDDrive]::deviceTypeMatches, returning FALSE\n",getName());
165: return(false); /* we don't handle other devices */
166: }
167: }
168:
169: IOReturn
170: IOSCSICDDrive::doAudioPlayCommand(positioningType startType,cdAddress startAddress,
171: positioningType endType,cdAddress endAddress)
172: {
173: struct context *cx;
174: struct IOAudioPlaycdb *c;
175: struct IOAudioPlayMSFcdb *p;
176: IOSCSICommand *req;
177: SCSICDBInfo scsiCDB;
178: IOReturn result;
179: UInt32 length;
180:
181: /* Can we return an error here, or must we ensure that start and stop are always
182: * locally converted to the same units before we use them?
183: */
184: if (startType != endType) {
185: return(kIOReturnBadArgument);
186: }
187:
188: if (startType != kAbsoluteTime || startType != kBlockAddress) {
189: return(kIOReturnBadArgument);
190: }
191:
192: cx = allocateContext();
193: if (cx == NULL) {
194: return(kIOReturnNoMemory);
195: }
196:
197: req = cx->scsireq;
198:
199: bzero( &scsiCDB, sizeof(scsiCDB) );
200:
201: if (startType == kBlockAddress) { /* use PlayAudio command */
202: c = (struct IOAudioPlaycdb *)scsiCDB.cdb;
203:
204: c->opcode = SOP_PLAYAUDIO;
205: c->lunbits = 0;
206: c->lba_3 = startAddress >> 24;
207: c->lba_2 = startAddress >> 16;
208: c->lba_1 = startAddress >> 8;
209: c->lba_0 = startAddress & 0xff;
210: c->reserved1 = 0;
211: length = endAddress - startAddress;
212: c->len_hi = length >> 8;
213: c->len_lo = length & 0xff;
214: c->ctlbyte = 0;
215:
216: } else { /* absolute time: use PlayAudioMSF */
217:
218: p = (struct IOAudioPlayMSFcdb *)scsiCDB.cdb;
219:
220: p->opcode = SOP_PLAYAUDIOMSF;
221: p->lunbits = 0;
222: p->reserved1 = 0;
223: p->start_m = startAddress >> 16;
224: p->start_s = startAddress >> 8;
225: p->start_f = startAddress & 0xff;
226: p->end_m = endAddress >> 16;
227: p->end_s = endAddress >> 8;
228: p->end_f = endAddress & 0xff;
229: p->ctlbyte = 0;
230: }
231:
232: scsiCDB.cdbLength = 10;
233: req->setCDB( &scsiCDB );
234: req->setPointers(cx->senseDataDesc, 255, false, true);
235:
236: req->setPointers( cx->memory, 0, false );
237: req->setTimeout( 1000 );
238:
239: result = simpleSynchIO(cx);
240:
241: deleteContext(cx);
242:
243: return(result);
244: }
245:
246: IOReturn
247: IOSCSICDDrive::getAudioStatus(struct audioStatus *status)
248: {
249: const UInt8 qBufLen = 16;
250: IOReturn result;
251: UInt8 *tempBuf;
252:
253: /* Get a buffer for the returned data: */
254:
255: result = allocateTempBuffer(&tempBuf,qBufLen);
256: if (result != kIOReturnSuccess) {
257: return(kIOReturnNoMemory);
258: }
259:
260: result = readSubchannel(tempBuf,qBufLen,0,IORSCcdb::kCurrentPosition);
261:
262: if ((result == kIOReturnSuccess) && ((tempBuf[5] & 0xf0) == 0x10)) { /* we got the data */
263: status->playMode = _audioPlayMode;
264: status->type = (trackType)(tempBuf[5] & 0xff);
265: status->address = tempBuf[ 9] << 16 |
266: tempBuf[10] << 8 |
267: tempBuf[11];
268: switch (tempBuf[1]) { /* convert audio status */
269:
270:
271: case 0x11:
272: status->status = kAudioPlayInProgress;
273: break;
274:
275: case 0x12:
276: status->status = kHoldTrackMode;
277: break;
278:
279: case 0x13:
280: status->status = kAudioPlayCompleted;
281: break;
282:
283: case 0x14:
284: status->status = kError;
285: break;
286:
287: case 0x15:
288: status->status = kAudioPlayNotRequested;
289: break;
290:
291: case 0x00:
292: default:
293: status->status = kUnknown;
294: break;
295: }
296: }
297: deleteTempBuffer(tempBuf,qBufLen);
298:
299: return(result);
300: }
301:
302: const char *
303: IOSCSICDDrive::getDeviceTypeName(void)
304: {
305: return(kDeviceTypeCDROM);
306: }
307:
308: bool
309: IOSCSICDDrive::init(OSDictionary * properties)
310: {
311: initAudioModes();
312:
313: _audioStopAddress.address = 0L;
314: _audioStopAddress.type = kBlockAddress;
315:
316: return(super::init(properties));
317: }
318:
319: void
320: IOSCSICDDrive::initAudioModes(void)
321: {
322: _audioPlayMode = stereo;
323: _leftVolume = 0xff;
324: _leftPortChannel = playModeToDriveBits(_audioPlayMode,kLeft);
325: _rightVolume = 0xff;
326: _rightPortChannel = playModeToDriveBits(_audioPlayMode,kRight);
327: }
328:
329: IOService *
330: IOSCSICDDrive::instantiateNub(void)
331: {
332: IOService *nub;
333:
334: /* Instantiate a generic CDROM nub so a generic driver can match above us. */
335:
336: nub = new IOSCSICDDriveNub;
337: return(nub);
338: }
339:
340: void
341: IOSCSICDDrive::mediaGone(void)
342: {
343: }
344:
345: /* Convert the audioPlayMode signal routing bits to the drive's bits. */
346:
347: UInt8
348: IOSCSICDDrive::playModeToDriveBits(audioPlayMode mode,channel chan)
349: {
350: UInt8 bits;
351: int shift;
352:
353: bits = 0;
354:
355: switch (chan) {
356:
357: case kLeft : shift = shift_Left_Channel; break;
358: case kRight : shift = shift_Right_Channel; break;
359:
360: default : return(bits);
361: }
362:
363: if (mode & (signal_Left << shift)) {
364: bits |= drive_left_signal;
365: }
366: if (mode & (signal_Right << shift)) {
367: bits |= drive_right_signal;
368: }
369:
370: return(bits);
371: }
372:
373: IOReturn
374: IOSCSICDDrive::readAudioData(positioningType addressType,cdAddress address,
375: UInt8 blockCount,UInt8 *buffer)
376: {
377: /* what about buffer vs. IOMemoryDescriptor? */
378:
379: //xxxx
380: return(kIOReturnUnsupported);
381: }
382:
383: IOReturn
384: IOSCSICDDrive::readAudioSubcodes(positioningType addressType,cdAddress address,
385: UInt8 blockCount,UInt8 *buffer)
386: {
387: /* what about buffer vs. IOMemoryDescriptor? */
388:
389: // xxxx
390: return(kIOReturnUnsupported);
391: }
392:
393: IOReturn
394: IOSCSICDDrive::readAudioVolume(UInt8 *leftVolume,UInt8 *rightVolume)
395: {
396: /* Return the cached values. */
397:
398: *leftVolume = _leftVolume;
399: *rightVolume = _rightVolume;
400:
401: return(kIOReturnSuccess);
402: }
403:
404: IOReturn
405: IOSCSICDDrive::readAudioWithQSubcode(positioningType addressType,cdAddress address,
406: UInt8 blockCount,UInt8 *buffer)
407: {
408: /* what about buffer vs. IOMemoryDescriptor? */
409:
410: //xxxx
411: return(kIOReturnUnsupported);
412: }
413:
414: IOReturn
415: IOSCSICDDrive::readAudioWithAllSubcodes(positioningType addressType,cdAddress address,
416: UInt8 blockCount,UInt8 *buffer)
417: {
418: /* what about buffer vs. IOMemoryDescriptor? */
419:
420: //xxxx
421: return(kIOReturnUnsupported);
422: }
423:
424: IOReturn
425: IOSCSICDDrive::readHeader(UInt32 blockAddress,struct headerInfo *buffer)
426: {
427: const UInt8 hdrBufLen = 24;
428: struct context *cx;
429: struct IOReadHeadercdb *c;
430: IOSCSICommand *req;
431: SCSICDBInfo scsiCDB;
432: IOReturn result;
433: UInt8 *tempBuf;
434:
435: bzero(buffer,sizeof(struct headerInfo));
436:
437: /* Get a buffer for the returned data: */
438:
439: result = allocateTempBuffer(&tempBuf,hdrBufLen);
440: if (result != kIOReturnSuccess) {
441: return(kIOReturnNoMemory);
442: }
443:
444: cx = allocateContext();
445: if (cx == NULL) {
446: return(kIOReturnNoMemory);
447: }
448:
449: req = cx->scsireq;
450:
451: bzero( &scsiCDB, sizeof(scsiCDB) );
452:
453: c = (struct IOReadHeadercdb *)scsiCDB.cdb;
454:
455: c->opcode = SOP_READHEADER;
456: c->lunbits = 0;
457: c->lunbits |= IOReadHeadercdb::kMSF; /* return results in M:S:F format */
458: c->lba_3 = blockAddress >> 24;
459: c->lba_2 = blockAddress >> 18;
460: c->lba_1 = blockAddress >> 8;
461: c->lba_0 = blockAddress & 0xff;
462: c->reserved1 = 0;
463: c->len_hi = 0;
464: c->len_lo = hdrBufLen;
465: c->ctlbyte = 0;
466:
467: scsiCDB.cdbLength = 10;
468: req->setCDB( &scsiCDB );
469: req->setPointers(cx->senseDataDesc, 255, false, true);
470:
471: cx->memory = IOMemoryDescriptor::withAddress((void *)tempBuf,
472: hdrBufLen,
473: kIODirectionIn);
474: req->setPointers( cx->memory, hdrBufLen, false );
475:
476: req->setTimeout( 1000 );
477:
478: result = simpleSynchIO(cx);
479:
480: deleteContext(cx);
481:
482: if (result == kIOReturnSuccess) { /* return the header info */
483: buffer->mode = (dataMode)(tempBuf[0]);
484: buffer->address = tempBuf[4] << 24 ||
485: tempBuf[5] << 16 ||
486: tempBuf[6] << 8 ||
487: tempBuf[7];
488: }
489:
490: deleteTempBuffer(tempBuf,hdrBufLen);
491:
492: return(result);
493: }
494:
495: IOReturn
496: IOSCSICDDrive::readISRC(UInt32 track,UInt8 *buffer,bool *found)
497: {
498: return(readISRCMCN(IORSCcdb::kISRC,track,buffer,found));
499: }
500:
501: /* Since the ISRC and MCN are the same size and behave the same, we use common code. */
502: IOReturn
503: IOSCSICDDrive::readISRCMCN(UInt8 dataformat,UInt32 track,UInt8 *buffer,bool *found)
504: {
505: const UInt8 mcnISRCBufLen = 24;
506: IOReturn result;
507: UInt8 *tempBuf;
508:
509: *found = false; /* assume no ISRC/MCN will be found */
510: bzero(buffer,mcnISRCBufLen);
511:
512: /* Get a buffer for the returned data: */
513:
514: result = allocateTempBuffer(&tempBuf,mcnISRCBufLen);
515: if (result != kIOReturnSuccess) {
516: return(kIOReturnNoMemory);
517: }
518:
519: result = readSubchannel(tempBuf,mcnISRCBufLen,track,dataformat);
520:
521: if ((result == kIOReturnSuccess) && (tempBuf[8] & 0x80)) { /* return the ISRC/MCN */
522: bcopy(buffer,&tempBuf[9],15);
523: *found = true;
524: }
525:
526: deleteTempBuffer(tempBuf,mcnISRCBufLen);
527:
528: return(result);
529: }
530:
531: IOReturn
532: IOSCSICDDrive::readMCN(UInt8 *buffer,bool *found)
533: {
534: return(readISRCMCN(IORSCcdb::kMCN,0,buffer,found)); /* any track will do */
535: }
536:
537:
538: IOReturn
539: IOSCSICDDrive::readQSubcodes(struct qSubcodeTocInfo *buffer,UInt32 bufSize)
540: {
541: /* what about buffer vs. IOMemoryDescriptor? */
542:
543: //xxxx
544: return(kIOReturnUnsupported);
545: }
546:
547: IOReturn
548: IOSCSICDDrive::readSubcodeBuffer(UInt8 *buffer,bool purge,UInt32 entryCount)
549: {
550: /* what about buffer vs. IOMemoryDescriptor? */
551:
552: //xxxx
553: return(kIOReturnUnsupported);
554: }
555:
556: IOReturn
557: IOSCSICDDrive::readSubchannel(UInt8 *buffer,UInt32 length,UInt8 track,UInt8 dataFormat)
558: {
559: struct context *cx;
560: struct IORSCcdb *c;
561: IOSCSICommand *req;
562: SCSICDBInfo scsiCDB;
563: IOReturn result;
564:
565: cx = allocateContext();
566: if (cx == NULL) {
567: return(kIOReturnNoMemory);
568: }
569:
570: req = cx->scsireq;
571:
572: bzero( &scsiCDB, sizeof(scsiCDB) );
573:
574: bzero(buffer,length);
575:
576: c = (struct IORSCcdb *)(scsiCDB.cdb);
577:
578: c->opcode = SOP_READSUBCHANNEL;
579: c->lunbits = 0;
580: c->lunbits |= IORSCcdb::kMSF;
581: c->subq = IORSCcdb::kSubq;
582: c->dataformat = dataFormat;
583: c->track = track; /* any valid track will do */
584: c->reserved1 = 0;
585: c->reserved2 = 0;
586: c->len_hi = length >> 8;
587: c->len_lo = length & 0xff;
588: c->ctlbyte = 0;
589:
590: scsiCDB.cdbLength = 10;
591: req->setCDB( &scsiCDB );
592: req->setPointers(cx->senseDataDesc, 255, false, true);
593:
594: cx->memory = IOMemoryDescriptor::withAddress((void *)buffer,
595: length,
596: kIODirectionIn);
597: req->setPointers( cx->memory, length, false );
598:
599: req->setTimeout( 1000 );
600:
601: result = simpleSynchIO(cx);
602:
603: deleteContext(cx);
604:
605: return(result);
606: }
607:
608: IOReturn
609: IOSCSICDDrive::readTheQSubcode(struct qSubcode *buffer)
610: {
611: const UInt8 qBufLen = 16;
612: IOReturn result;
613: UInt8 *tempBuf;
614:
615: bzero(buffer,sizeof(struct qSubcode));
616:
617: /* Get a buffer for the returned data: */
618:
619: result = allocateTempBuffer(&tempBuf,qBufLen);
620: if (result != kIOReturnSuccess) {
621: return(kIOReturnNoMemory);
622: }
623:
624: result = readSubchannel(tempBuf,qBufLen,0, IORSCcdb::kCurrentPosition);
625:
626: if ((result == kIOReturnSuccess) && ((tempBuf[5] & 0xf0) == 0x10)) { /* we got the data */
627: buffer->type = (trackType)(tempBuf[ 5] & 0x0f);
628: buffer->track = tempBuf[ 6];
629: buffer->index = tempBuf[ 7];
630: buffer->absAddress = tempBuf[ 9] << 16 |
631: tempBuf[10] << 8 |
632: tempBuf[11];
633: buffer->relAddress = tempBuf[13] << 16 |
634: tempBuf[14] << 8 |
635: tempBuf[15];
636: }
637:
638: deleteTempBuffer(tempBuf,qBufLen);
639:
640: return(result);
641: }
642:
643: IOReturn
644: IOSCSICDDrive::readTOC(struct rawToc *buffer,UInt32 length,tocFormat format)
645: {
646: struct context *cx;
647: struct IOReadToccdb *c;
648: IOSCSICommand *req;
649: SCSICDBInfo scsiCDB;
650: IOReturn result;
651:
652: cx = allocateContext();
653: if (cx == NULL) {
654: return(kIOReturnNoMemory);
655: }
656:
657: req = cx->scsireq;
658:
659: bzero( &scsiCDB, sizeof(scsiCDB) );
660:
661: c = (struct IOReadToccdb *)scsiCDB.cdb;
662:
663: c->opcode = SOP_READTOC;
664: c->lunbits = 0;
665: if (format == ktocSCSI2MSF) {
666: c->lunbits |= IOReadToccdb::kMSF;
667: }
668: c->reserved1 = 0;
669: c->reserved2 = 0;
670: c->reserved3 = 0;
671: c->reserved4 = 0;
672: c->len_hi = length >> 8;
673: c->len_lo = length & 0xff;
674: c->ctlbyte = 0;
675:
676: switch (format) {
677: case ktocSCSI2MSF :
678: case ktocSCSI2LBA :
679: c->ctlbyte |= IOReadToccdb::kSCSI2;
680: break;
681:
682: case ktocSessionInfo :
683: c->ctlbyte |= IOReadToccdb::kSessionInfo;
684: break;
685:
686: case ktocQLeadin :
687: c->ctlbyte |= IOReadToccdb::kQLeadIn;
688: break;
689: }
690:
691: scsiCDB.cdbLength = 10;
692: req->setCDB( &scsiCDB );
693: req->setPointers(cx->senseDataDesc, 255, false, true);
694:
695: cx->memory = IOMemoryDescriptor::withAddress((void *)buffer,
696: length,
697: kIODirectionIn);
698: req->setPointers( cx->memory, length, false );
699:
700: req->setTimeout( 1000 );
701:
702: result = simpleSynchIO(cx);
703:
704: if ( result == kIOReturnUnderrun ) result = kIOReturnSuccess;
705:
706: deleteContext(cx);
707:
708: return(result);
709: }
710:
711: /* We track media changes so we can:
712: * - set default audio playMode and volume
713: */
714:
715: IOReturn
716: IOSCSICDDrive::reportMediaState(bool *mediaPresent,bool *changed)
717: {
718: IOReturn result;
719: IOReturn internalResult;
720:
721: result = super::reportMediaState(mediaPresent,changed);
722:
723: /**
724: IOLog("%s[IOSCSICDDrive]::reportMediaState; result=%s, changed = %s, present = %s\n",
725: getName(),stringFromReturn(result),*changed ? "Y" : "N", *mediaPresent ? "Y" : "N");
726: **/
727:
728: if ((result == kIOReturnSuccess) && *changed) { /* the media state changed */
729: if (*mediaPresent) { /* new media inserted */
730: internalResult = setDefaultAudioModes();
731: } else { /* media went away */
732: mediaGone();
733: }
734: }
735:
736: /* We don't return the result of our internal operations. But since they
737: * indicate a problem, we probably should report some kind of problem,
738: * or maybe just ignore the media change.
739: */
740:
741: return(result);
742: }
743:
744: IOReturn
745: IOSCSICDDrive::seek(UInt32 lba)
746: {
747: struct context *cx;
748: struct IOSeekcdb *c;
749: IOSCSICommand *req;
750: SCSICDBInfo scsiCDB;
751: IOReturn result;
752:
753: cx = allocateContext();
754: if (cx == NULL) {
755: return(kIOReturnNoMemory);
756: }
757:
758: req = cx->scsireq;
759:
760: bzero( &scsiCDB, sizeof(scsiCDB) );
761:
762: c = (struct IOSeekcdb *)(scsiCDB.cdb);
763:
764: c->opcode = SOP_SEEK;
765: c->lunbits = 0;
766: c->lba_3 = lba >> 24;
767: c->lba_2 = lba >> 16;
768: c->lba_1 = lba >> 8;
769: c->lba_0 = lba & 0xff;
770: c->reserved1 = 0;
771: c->reserved2 = 0;
772: c->reserved3 = 0;
773: c->ctlbyte = 0;
774:
775: scsiCDB.cdbLength = 10;
776: req->setCDB( &scsiCDB );
777: req->setPointers(cx->senseDataDesc, 255, false, true);
778:
779: req->setPointers( cx->memory, 0, false );
780:
781: req->setTimeout( 5000 );
782:
783: result = simpleSynchIO(cx);
784:
785: deleteContext(cx);
786:
787: return(result);
788: }
789:
790: IOReturn
791: IOSCSICDDrive::setAudioStopAddress(positioningType addressType,cdAddress address)
792: {
793: /* We have to stash the stop address locally, because the client often sets
794: * the stop address before providing the start address. We can't send the
795: * stop address to the drive without a valid start address, because the pickup
796: * could be currently over a data track, which would return an error.
797: */
798:
799: _audioStopAddress.type = addressType;
800: _audioStopAddress.address = address;
801:
802: /* If the address is for block=0, we must stop any audio play in progress. */
803:
804: if (addressType == kBlockAddress && address == 0L) { /* stop play */
805: return(doAudioPlayCommand(kAbsoluteTime,0xffffff,kAbsoluteTime,0));
806: } else { /* set new stop addr */
807: return(doAudioPlayCommand(kAbsoluteTime,0xffffff,addressType,address));
808: }
809: }
810:
811: IOReturn
812: IOSCSICDDrive::setDefaultAudioModes(void)
813: {
814: initAudioModes();
815: return(setVolume(_leftVolume,_rightVolume));
816: }
817:
818: struct audioPage {
819: UInt8 pagecode;
820: UInt8 paramlen;
821: UInt8 immed;
822: UInt8 reserved[5];
823: UInt8 leftportchannel;
824: UInt8 leftvolume;
825: UInt8 rightportchannel;
826: UInt8 rightvolume;
827: UInt8 port2channel;
828: UInt8 port2volume;
829: UInt8 port3channel;
830: UInt8 port3volume;
831: };
832:
833: IOReturn
834: IOSCSICDDrive::setVolume(UInt8 leftVolume,UInt8 rightVolume)
835: {
836: struct context *cx;
837: struct IOModeSelectcdb *c;
838: IOSCSICommand *req;
839: SCSICDBInfo scsiCDB;
840: IOReturn result;
841: struct audioPage *page;
842:
843: cx = allocateContext();
844: if (cx == NULL) {
845: return(kIOReturnNoMemory);
846: }
847:
848: req = cx->scsireq;
849:
850: bzero( &scsiCDB, sizeof(scsiCDB) );
851:
852: /* Set up a Mode Select for page 0x0e. We set volume and audioPlay mode. */
853:
854: result = allocateTempBuffer((UInt8 **)(&page),sizeof(struct audioPage));
855: if (result != kIOReturnSuccess) {
856: deleteContext(cx);
857: return(kIOReturnNoMemory);
858: }
859:
860: bzero(page,sizeof(struct audioPage)),
861: page->pagecode = 0x0e;
862: page->paramlen = 0x0e;
863:
864: page->leftportchannel = playModeToDriveBits(_audioPlayMode,kLeft);
865: page->leftvolume = leftVolume;
866: page->rightportchannel = playModeToDriveBits(_audioPlayMode,kRight);
867: page->rightvolume = rightVolume;
868:
869: c = (struct IOModeSelectcdb *)(scsiCDB.cdb);
870:
871: c->opcode = SOP_MODESELECT;
872: c->lunbits = 0;
873: c->reserved1 = 0;
874: c->reserved2 = 0;
875: c->paramlen = sizeof(struct audioPage);
876: c->ctlbyte = 0;
877:
878: // IOLog("%s[IOSCSICDDrive::setVolume\n",getName());
879:
880: scsiCDB.cdbLength = 6;
881: req->setCDB( &scsiCDB );
882: req->setPointers(cx->senseDataDesc, 255, false, true);
883:
884: cx->memory = IOMemoryDescriptor::withAddress((void *)page,
885: c->paramlen,
886: kIODirectionOut);
887: req->setPointers( cx->memory, c->paramlen, true );
888:
889: req->setTimeout( 1000 );
890:
891: result = simpleSynchIO(cx);
892:
893: deleteTempBuffer((UInt8 *)page,sizeof(struct audioPage));
894: deleteContext(cx);
895:
896: if (result == kIOReturnSuccess) { /* only remember settings if they worked */
897: _leftVolume = leftVolume;
898: _rightVolume = rightVolume;
899: }
900:
901: return(result);
902: }
903:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.