|
|
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: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
24: *
25: * IOATAPIHDDrive.h - Generic ATAPI Direct-Access driver.
26: *
27: * HISTORY
28: * Sep 2, 1999 jliu - Ported from AppleATAPIDrive.
29: */
30:
31: #include <IOKit/assert.h>
32: #include <IOKit/storage/ata/IOATAPIHDDrive.h>
33: #include <IOKit/storage/ata/IOATAPIHDDriveNub.h>
34:
35: #define super IOATAHDDrive
36: OSDefineMetaClassAndStructors( IOATAPIHDDrive, IOATAHDDrive )
37:
38: // --------------------------------------------------------------------------
39: // Override the init() method in IOATAHDDrive.
40:
41: bool
42: IOATAPIHDDrive::init(OSDictionary * properties)
43: {
44: _mediaPresent = false;
45: _isRemovable = false;
46:
47: return (super::init(properties));
48: }
49:
50: // --------------------------------------------------------------------------
51: // Override probe() method inherited from IOATAHDDrive. We need to
52: // perform additional matching on ATAPI device type from the Inquiry data.
53:
54: IOService *
55: IOATAPIHDDrive::probe(IOService * provider, SInt32 * score)
56: {
57: UInt8 deviceType;
58:
59: // Our provider must be a IOATADevice nub, most likely created
60: // by an IOATAController instance.
61: //
62: IOATADevice * device = OSDynamicCast(IOATADevice, provider);
63: if (!device)
64: return 0; // IOATADevice nub not found.
65:
66: // Let superclass have a go at probe first.
67: //
68: if (!super::probe(provider, score))
69: return 0;
70:
71: // Perform ATAPI type matching, CD-ROM, Direct-Access, Tape, etc.
72: //
73: if (!device->getInquiryData(1, (ATAPIInquiry *) &deviceType) ||
74: !matchATAPIDeviceType(deviceType & 0x1f))
75: return 0;
76:
77: return this; // probe successful.
78: }
79:
80: // --------------------------------------------------------------------------
81: // Report as an ATAPI device.
82:
83: ATADeviceType
84: IOATAPIHDDrive::reportATADeviceType() const
85: {
86: return ataDeviceATAPI;
87: }
88:
89: // --------------------------------------------------------------------------
90: // Looks for an ATAPI device which is a direct-access device.
91:
92: bool
93: IOATAPIHDDrive::matchATAPIDeviceType(UInt8 type)
94: {
95: if (type == kIOATAPIDeviceTypeDirectAccess)
96: return true;
97: return false;
98: }
99:
100: // --------------------------------------------------------------------------
101: // Gather information about the ATAPI device nub.
102:
103: void
104: IOATAPIHDDrive::inspectDevice(IOService * provider)
105: {
106: OSString * string;
107: IOATADevice * ataDevice = OSDynamicCast(IOATADevice, provider);
108: if (!ataDevice)
109: return;
110:
111: // Fetch ATAPI device information from the nub.
112: //
113: string = OSDynamicCast(OSString,
114: ataDevice->getProperty(ATAPropertyVendorName));
115: if (string) {
116: strncpy(_vendor, string->getCStringNoCopy(), 8);
117: _vendor[8] = '\0';
118: }
119:
120: string = OSDynamicCast(OSString,
121: ataDevice->getProperty(ATAPropertyProductName));
122: if (string) {
123: strncpy(_product, string->getCStringNoCopy(), 16);
124: _product[16] = '\0';
125: }
126:
127: string = OSDynamicCast(OSString,
128: ataDevice->getProperty(ATAPropertyProductRevision));
129: if (string) {
130: strncpy(_revision, string->getCStringNoCopy(), 4);
131: _revision[4] = '\0';
132: }
133: }
134:
135: // --------------------------------------------------------------------------
136: // Handles read/write requests.
137:
138: IOReturn IOATAPIHDDrive::doAsyncReadWrite(IOMemoryDescriptor * buffer,
139: UInt32 block,
140: UInt32 nblks,
141: gdCompletionFunction action,
142: IOService * target,
143: void * param)
144: {
145: IOReturn ret;
146: IOATACommand * cmd = atapiCommandReadWrite(buffer, block, nblks);
147: if (!cmd)
148: return kIOReturnNoMemory;
149:
150: ret = getIOReturn(asyncExecute(cmd, target, action, param));
151:
152: cmd->release();
153:
154: return ret;
155: }
156:
157: // --------------------------------------------------------------------------
158: // Eject the media in the removable drive.
159:
160: IOReturn
161: IOATAPIHDDrive::doEjectMedia()
162: {
163: IOReturn ret;
164: IOATACommand * cmd = atapiCommandStartStopUnit(0, /* senseData */
165: false, /* start unit */
166: true, /* Load/Eject */
167: false); /* Immediate */
168:
169: if (!cmd)
170: return kIOReturnNoMemory;
171:
172: ret = getIOReturn(syncExecute(cmd));
173:
174: cmd->release();
175:
176: return ret;
177: }
178:
179: // --------------------------------------------------------------------------
180: // Format the media in the drive.
181:
182: IOReturn
183: IOATAPIHDDrive::doFormatMedia(UInt64 /* byteCapacity */)
184: {
185: return kIOReturnUnsupported;
186: }
187:
188: // --------------------------------------------------------------------------
189: // Lock/unlock the media in the removable drive.
190:
191: IOReturn
192: IOATAPIHDDrive::doLockUnlockMedia(bool doLock)
193: {
194: IOReturn ret;
195: IOATACommand * cmd = atapiCommandPreventAllowRemoval(doLock);
196: if (!cmd)
197: return kIOReturnNoMemory;
198:
199: ret = getIOReturn(syncExecute(cmd));
200:
201: cmd->release();
202:
203: return ret;
204: }
205:
206: // --------------------------------------------------------------------------
207: // Sync the write cache.
208:
209: IOReturn
210: IOATAPIHDDrive::doSynchronizeCache()
211: {
212: return kIOReturnSuccess;
213: }
214:
215: // --------------------------------------------------------------------------
216: // Start up the drive.
217:
218: IOReturn
219: IOATAPIHDDrive::doStart()
220: {
221: return doStartStop(true);
222: }
223:
224: // --------------------------------------------------------------------------
225: // Stop the drive.
226:
227: IOReturn
228: IOATAPIHDDrive::doStop()
229: {
230: return doStartStop(false);
231: }
232:
233: // --------------------------------------------------------------------------
234: // Issue a START/STOP Unit command.
235:
236: IOReturn
237: IOATAPIHDDrive::doStartStop(bool doStart)
238: {
239: IOReturn ret;
240: IOATACommand * cmd;
241:
242: cmd = atapiCommandStartStopUnit(0, /* senseData */
243: doStart, /* start unit */
244: false, /* Load/Eject */
245: false); /* Immediate operation */
246:
247: if (!cmd) return kIOReturnNoMemory;
248:
249: ret = getIOReturn(syncExecute(cmd));
250:
251: cmd->release();
252:
253: return ret;
254: }
255:
256: // --------------------------------------------------------------------------
257: // Return device identification strings
258:
259: char * IOATAPIHDDrive::getVendorString()
260: {
261: return _vendor;
262: }
263:
264: char * IOATAPIHDDrive::getProductString()
265: {
266: return _product;
267: }
268:
269: char * IOATAPIHDDrive::getRevisionString()
270: {
271: return _revision;
272: }
273:
274: char * IOATAPIHDDrive::getAdditionalDeviceInfoString()
275: {
276: return ("[ATAPI]");
277: }
278:
279: // --------------------------------------------------------------------------
280: // Report whether the media in the drive is ejectable.
281:
282: IOReturn
283: IOATAPIHDDrive::reportEjectability(bool * isEjectable)
284: {
285: *isEjectable = true; /* default: if it's removable, it's ejectable */
286: return kIOReturnSuccess;
287: }
288:
289: // --------------------------------------------------------------------------
290: // Report whether the drive can prevent user-initiated ejects by locking
291: // the media in the drive.
292:
293: IOReturn
294: IOATAPIHDDrive::reportLockability(bool * isLockable)
295: {
296: *isLockable = true; /* default: if it's removable, it's lockable */
297: return kIOReturnSuccess;
298: }
299:
300: // --------------------------------------------------------------------------
301: // Report our polling requirments.
302:
303: IOReturn
304: IOATAPIHDDrive::reportPollRequirements(bool * pollRequired,
305: bool * pollIsExpensive)
306: {
307: *pollIsExpensive = false;
308: *pollRequired = _isRemovable;
309: return kIOReturnSuccess;
310: }
311:
312: // --------------------------------------------------------------------------
313: // Report the current state of the media.
314:
315: IOReturn
316: IOATAPIHDDrive::reportMediaState(bool * mediaPresent,
317: bool * changed)
318: {
319: IOATACommand * cmd;
320: ATAResults results;
321: IOReturn ret = kIOReturnSuccess;
322: UInt8 senseData[18];
323: IOMemoryDescriptor * senseDesc;
324:
325: assert(mediaPresent && changed);
326:
327: senseDesc = IOMemoryDescriptor::withAddress(senseData,
328: sizeof(senseData),
329: kIODirectionIn);
330: if (!senseDesc)
331: return kIOReturnNoMemory;
332:
333: cmd = atapiCommandTestUnitReady(senseDesc);
334: if (!cmd)
335: return kIOReturnNoMemory;
336:
337: // Execute the Test Unit Ready command with no retries.
338: //
339: syncExecute(cmd, ATADefaultTimeout, 0);
340:
341: // Release the memory descriptor.
342: //
343: senseDesc->release();
344:
345: if (cmd->getResults(&results) == ataReturnNoError)
346: {
347: *mediaPresent = true;
348: *changed = (*mediaPresent != _mediaPresent);
349: _mediaPresent = true;
350: }
351: else
352: {
353: UInt8 errorCode = senseData[0];
354: UInt8 senseKey = senseData[2];
355:
356: #ifdef DEBUG_LOG
357: UInt8 senseCode = senseData[12];
358: UInt8 senseQualifier = senseData[13];
359:
360: IOLog("-- reportMediaState --\n");
361: IOLog("Error code: %02x\n", errorCode);
362: IOLog("Sense Key : %02x\n", senseKey);
363: IOLog("ASC : %02x\n", senseCode);
364: IOLog("ASCQ : %02x\n", senseQualifier);
365: #endif
366:
367: *mediaPresent = false;
368: *changed = (*mediaPresent != _mediaPresent);
369: _mediaPresent = false;
370:
371: // The error code field for ATAPI request sense should always
372: // be 0x70 or 0x71. Otherwise ignore the sense data.
373: //
374: if ((errorCode == 0x70) || (errorCode == 0x71))
375: {
376: switch (senseKey) {
377: case 5: /* Invalid ATAPI command */
378: ret = kIOReturnIOError;
379: break;
380:
381: case 2: /* Not ready */
382: break;
383:
384: default:
385: break;
386: }
387: }
388: }
389:
390: cmd->release();
391:
392: #if 0
393: IOLog("%s: media present %s, changed %s\n", getName(),
394: *mediaPresent ? "Y" : "N",
395: *changed ? "Y" : "N"
396: );
397: #endif
398:
399: #ifndef DISKPM
400: if (*changed && *mediaPresent)
401: doStart();
402: #endif
403:
404: return ret;
405: }
406:
407: // --------------------------------------------------------------------------
408: // Report media removability.
409:
410: IOReturn
411: IOATAPIHDDrive::reportRemovability(bool * isRemovable)
412: {
413: UInt8 inqBuf[2];
414:
415: *isRemovable = false;
416:
417: if (_ataDevice->getInquiryData(sizeof(inqBuf), (ATAPIInquiry *) inqBuf))
418: {
419: if (inqBuf[1] & 0x80)
420: *isRemovable = _isRemovable = true;
421: else
422: *isRemovable = _isRemovable = false;
423: }
424:
425: return kIOReturnSuccess;
426: }
427:
428: // --------------------------------------------------------------------------
429: // Report whether media is write-protected.
430:
431: IOReturn
432: IOATAPIHDDrive::reportWriteProtection(bool * isWriteProtected)
433: {
434: *isWriteProtected = false; // defaults to read-write
435: return kIOReturnSuccess;
436: }
437:
438: // --------------------------------------------------------------------------
439: // Instantiate an ATAPI specific subclass of IOHDDriveNub.
440:
441: IOService *
442: IOATAPIHDDrive::instantiateNub()
443: {
444: IOService * nub = new IOATAPIHDDriveNub;
445: return nub;
446: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.