-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathIOATABlockStorageDriver.h
573 lines (413 loc) · 19.9 KB
/
IOATABlockStorageDriver.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
/*
* Copyright (c) 1998-2003 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#ifndef _IO_ATA_BLOCKSTORAGE_DRIVER_PD_H_
#define _IO_ATA_BLOCKSTORAGE_DRIVER_PD_H_
/* osfmk includes */
#include <kern/queue.h>
/* General IOKit includes */
#include <IOKit/IOLib.h>
#include <IOKit/IOMessage.h>
#include <IOKit/IOService.h>
#include <IOKit/IOSyncer.h>
#include <IOKit/IOCommandGate.h>
#include <IOKit/IOCommandPool.h>
/* IOKit ATA includes */
#include <IOKit/storage/IOStorage.h>
#include "IOATAStorageDefines.h"
#include <IOKit/ata/IOATADevice.h>
#include <IOKit/ata/IOATATypes.h>
// Forward class declaration
class IOATABlockStorageDriver_PD;
/*!
@typedef ATAClientData
@param cmd IOATACommand for request.
@param self Pointer to the object.
@param completion Either the async completion structure or an IOSyncer to wake up.
@param isSync Flag - tells whether the command was sync or async.
@param maxRetries Maxiumum number of retry attempts per I/O.
@param returnCode Return code (errors).
@param buffer Original memory descriptor.
@param bufferOffset Offset into client's buffer.
@param startBlock Original starting block.
@param numberOfBlocks Original number of requested blocks.
@param opCode ATA opcode.
@param flags Flags to use for the operation.
@param timeout Timeout value in milliseconds.
@param regMask Register Mask.
@param featuresReg Features register.
@param sdhReg The SDH register
@param command The command register.
@param cylHigh The Cylinder high bits.
@param cylLow The Cylinder low bits.
@param sectorNumber The Sector Number register.
@param sectorCount The Sector Count register.
@discussion This structure is stuffed into the refcon so we can associate which
IOATACommand is completing.
*/
struct ATAClientData
{
IOATACommand * cmd; // pointer to command object this wraps
IOATABlockStorageDriver_PD * self; // pointer to self
union {
IOStorageCompletion async; // completion target/action/param.
IOSyncer * syncLock; // used by sync commands.
} completion;
bool isSync; // command is synchronous.
SInt32 maxRetries; // max retry attempts (0 = no retry).
IOReturn returnCode; // sync command return code.
IOMemoryDescriptor * buffer; // needed for retries
UInt32 bufferOffset; // offset into client buffer
UInt32 startBlock; // needed for retries
UInt32 numberOfBlocks; // needed for retries
// Saved state data for ATA registers
ataOpcode opCode; // Opcode of the desired operation
UInt32 flags; // Flags to use for this operation
UInt32 timeout; // Original timeout value
ataRegMask regMask; // Mask to tell controller what registers
// to read/write
UInt8 featuresReg; // Features register
UInt8 sdhReg; // Set Device Head register
UInt8 command; // Command to use for this operation
UInt8 cylHigh; // High bits of the cylinder register
UInt8 cylLow; // Low bits of the cylinder register
UInt8 sectorNumber; // Value of the sectorNumber register
UInt8 sectorCount; // Value of the sectorCount register
// added for 48-bit LBA support
bool useExtendedLBA;
UInt16 lbaLow16;
UInt16 lbaMid16;
UInt16 lbaHigh16;
UInt16 sectorCount16;
UInt16 features16;
UInt8 device;
UInt16 command16;
};
typedef struct ATAClientData ATAClientData;
// Property table keys
#define kIOATASupportedFeaturesKey "ATA Features"
class IOATABlockStorageDriver_PD : public IOService
{
OSDeclareDefaultStructors ( IOATABlockStorageDriver_PD )
protected:
IOATADevice * fATADevice;
ataUnitID fATAUnitID;
ataDeviceType fATADeviceType;
ataSocketType fATASocketType;
UInt8 fPIOMode;
UInt8 fDMAMode;
UInt8 fUltraDMAMode;
bool fUseLBAAddressing;
IOCommandPool * fCommandPool;
IOCommandGate * fCommandGate;
UInt32 fNumCommandObjects;
UInt32 fNumCommandsOutstanding;
// "Special commands"
IOATACommand * fResetCommand;
IOATACommand * fPowerManagementCommand;
IOATACommand * fConfigurationCommand;
UInt16 fDeviceIdentifyData[256];
IOMemoryDescriptor * fDeviceIdentifyBuffer;
char fRevision[ kSizeOfATARevisionString + 1 ];
char fModel[ kSizeOfATAModelString + 1 ];
UInt8 fAPMLevel;
IOOptionBits fSupportedFeatures;
thread_call_t fPowerManagementThread;
bool fWakeUpResetOccurred;
IOATAPowerState fCurrentPowerState;
IOATAPowerState fProposedPowerState;
bool fPowerTransitionInProgress;
bool fPowerManagementInitialized;
bool fResetInProgress;
// binary compatibility instance variable expansion
struct ExpansionData
{
bool fUseExtendedLBA;
bool fPowerAckInProgress;
IONotifier * fPowerDownNotifier;
};
ExpansionData * reserved;
#define fUseExtendedLBA reserved->fUseExtendedLBA
#define fPowerAckInProgress reserved->fPowerAckInProgress
#define fPowerDownNotifier reserved->fPowerDownNotifier
public:
// Called when system is going to power down
IOReturn powerDownHandler ( void * refCon,
UInt32 messageType,
IOService * provider,
void * messageArgument,
vm_size_t argSize );
protected:
//-----------------------------------------------------------------------
// Static member functions
static void sSwapBytes16 ( UInt8 * buffer, IOByteCount numBytesToSwap );
static UInt8 sConvertHighestBitToNumber ( UInt16 bitField );
static void sHandleCommandCompletion ( IOATACommand * cmd );
static void sHandleReset ( IOATACommand * cmd );
static void sPowerManagement ( thread_call_param_t whichDevice );
static void sHandleSetPowerState ( IOATABlockStorageDriver_PD * self,
UInt32 powerStateOrdinal );
static void sHandleCheckPowerState ( IOATABlockStorageDriver_PD * self );
static void sHandleSimpleSyncTransaction ( IOATACommand * cmd );
static void sConvertBlockToCHSAddress ( IOATACommand * cmd,
UInt32 block,
UInt32 heads,
UInt32 sectors,
ataUnitID unitID );
static void sReissueCommandFromClientData ( IOATACommand * cmd );
static void sSetCommandBuffers ( IOATACommand * cmd,
IOMemoryDescriptor * buffer,
IOByteCount offset,
IOByteCount numBlocks );
static void sSaveStateData ( IOATACommand * cmd );
static IOReturn sValidateIdentifyData ( UInt8 * deviceIdentifyData );
// The sSetWakeupResetOccurred method is used to safely set member variables
// behind the command gate.
static void sSetWakeupResetOccurred ( IOATABlockStorageDriver_PD * driver,
bool resetOccurred );
// The sCheckWakeupResetOccur method is used to safely check member variables
// behind the command gate.
static void sCheckWakeupResetOccurred ( IOATABlockStorageDriver_PD * driver,
void * resetOccurred );
static void sATAConfigStateMachine ( IOATACommand * cmd );
static void sATAVoidCallback ( IOATACommand * cmd );
//-----------------------------------------------------------------------
// Release all allocated resource before calling super::free().
virtual void free ( void ) APPLE_KEXT_OVERRIDE;
//-----------------------------------------------------------------------
// Stop any power management
virtual bool finalize ( IOOptionBits options ) APPLE_KEXT_OVERRIDE;
//-----------------------------------------------------------------------
// Setup an ATATaskFile from the parameters given
virtual void setupReadWriteTaskFile ( IOATACommand * cmd,
IOMemoryDescriptor * buffer,
UInt32 block,
UInt32 nblks );
//-----------------------------------------------------------------------
// Return an IOATACommand initialized to perform a read/write operation.
virtual IOATACommand * ataCommandReadWrite ( IOMemoryDescriptor * buffer,
UInt32 block,
UInt32 nblks );
//-----------------------------------------------------------------------
// Return an ATA Set Features command.
virtual IOReturn ataCommandSetFeatures ( UInt8 features,
UInt8 sectorCount = 0,
UInt8 sectorNumber = 0,
UInt8 cylinderLow = 0,
UInt8 cylinderHigh = 0,
UInt32 flags = 0,
bool forceSync = false );
//-----------------------------------------------------------------------
// Return an ATA Flush Cache command.
virtual IOATACommand * ataCommandFlushCache ( void );
//-----------------------------------------------------------------------
// Issues a power transition
virtual IOReturn issuePowerTransition ( UInt32 function );
//-----------------------------------------------------------------------
// Issue a synchronous ATA command.
virtual IOReturn syncExecute ( IOATACommand * cmd,
UInt32 timeout = kATADefaultTimeout,
UInt8 retries = kATADefaultRetries );
//-----------------------------------------------------------------------
// Issue an asynchronous ATA command.
virtual IOReturn asyncExecute (
IOATACommand * cmd,
IOStorageCompletion completion,
UInt32 timeout = kATADefaultTimeout,
UInt8 retries = kATADefaultRetries );
//-----------------------------------------------------------------------
// Inspect the ATA device.
virtual bool inspectDevice ( IOATADevice * device );
//-----------------------------------------------------------------------
// Returns an IOATABlockStorageDevice instance.
virtual IOService * instantiateNub ( void );
//-----------------------------------------------------------------------
// Calls instantiateNub() then initialize, attach, and register the
// drive nub.
virtual bool createNub ( IOService * provider );
//-----------------------------------------------------------------------
// Power management support. Subclasses can override these functions
// to replace/enhance the default power management support.
virtual void initForPM ( void );
virtual void handleSetPowerState ( UInt32 powerStateOrdinal );
//-----------------------------------------------------------------------
// Allocate/Deallocate ATA commands.
virtual void allocateATACommandObjects ( void );
virtual void deallocateATACommandObjects ( void );
//-----------------------------------------------------------------------
// Get/return ATA commands
virtual IOATACommand * getATACommandObject ( bool blockForCommand = true );
virtual void returnATACommandObject ( IOATACommand * cmd );
//-----------------------------------------------------------------------
// Initialization and Configuation calls
virtual IOReturn setPIOTransferMode ( bool forceSync );
virtual IOReturn setDMATransferMode ( bool forceSync );
virtual IOReturn identifyAndConfigureATADevice ( void );
virtual IOReturn configureATADevice ( void );
virtual IOReturn reconfigureATADevice ( void );
virtual IOReturn identifyATADevice ( void );
virtual IOReturn resetATADevice ( void );
// The checkWakeupResetOccurred method is used to safely find out if a reset
// occurred while we were asleep.
virtual bool checkWakeupResetOccurred ( void );
// The setWakeupResetOccurred method is used to safely set/clear the reset flag.
virtual void setWakeupResetOccurred ( bool resetOccurred );
public:
// Overrides from IOService
bool init ( OSDictionary * propertyTable ) APPLE_KEXT_OVERRIDE;
virtual bool start ( IOService * provider ) APPLE_KEXT_OVERRIDE;
virtual void stop ( IOService * provider ) APPLE_KEXT_OVERRIDE;
// Necessary for calls from user space to set the APM level.
virtual IOReturn setAdvancedPowerManagementLevel ( UInt8 level, bool forceSync );
//-----------------------------------------------------------------------
// Power management support. Functions inherited from IOService.
virtual IOReturn setAggressiveness ( UInt32 type, UInt32 minutes );
// The initialPowerStateForDomainState() method is called by the power manager
// to ask us what state we should be in based on the power flags of our parent
// in the power tree.
virtual unsigned long initialPowerStateForDomainState ( IOPMPowerFlags flags ) APPLE_KEXT_OVERRIDE;
virtual IOReturn setPowerState ( UInt32 powerStateOrdinal,
IOService * whatDevice );
//-----------------------------------------------------------------------
// Report the type of ATA device (ATA vs. ATAPI).
virtual ataDeviceType reportATADeviceType ( void ) const;
//-----------------------------------------------------------------------
// Handles read/write requests.
virtual IOReturn doAsyncReadWrite ( IOMemoryDescriptor * buffer,
UInt32 block,
UInt32 nblks,
IOStorageCompletion completion );
virtual IOReturn doSyncReadWrite ( IOMemoryDescriptor * buffer,
UInt32 block,
UInt32 nblks );
//-----------------------------------------------------------------------
// Eject the media in the drive.
virtual IOReturn doEjectMedia ( void );
//-----------------------------------------------------------------------
// Format the media in the drive.
virtual IOReturn doFormatMedia ( UInt64 byteCapacity );
//-----------------------------------------------------------------------
// Returns disk capacity in bytes.
virtual UInt32 doGetFormatCapacities ( UInt64 * capacities,
UInt32 capacitiesMaxCount ) const;
//-----------------------------------------------------------------------
// Lock the media and prevent a user-initiated eject.
virtual IOReturn doLockUnlockMedia ( bool doLock );
//-----------------------------------------------------------------------
// Flush the write-cache to the physical media.
virtual IOReturn doSynchronizeCache ( void );
//-----------------------------------------------------------------------
// Start/stop the drive.
virtual IOReturn doStart ( void );
virtual IOReturn doStop ( void );
//-----------------------------------------------------------------------
// Return device identification strings
virtual char * getAdditionalDeviceInfoString ( void );
virtual char * getProductString ( void );
virtual char * getRevisionString ( void );
virtual char * getVendorString ( void );
//-----------------------------------------------------------------------
// Report the device block size in bytes.
virtual IOReturn reportBlockSize ( UInt64 * blockSize );
//-----------------------------------------------------------------------
// Report whether the media in the ATA device is ejectable.
virtual IOReturn reportEjectability ( bool * isEjectable );
//-----------------------------------------------------------------------
// Report whether the media can be locked.
virtual IOReturn reportLockability ( bool * isLockable );
//-----------------------------------------------------------------------
// Report the polling requirements for a removable media.
virtual IOReturn reportPollRequirements ( bool * pollRequired,
bool * pollIsExpensive );
//-----------------------------------------------------------------------
// Report the max number of bytes transferred for an ATA read command.
virtual IOReturn reportMaxReadTransfer ( UInt64 blocksize,
UInt64 * max );
//-----------------------------------------------------------------------
// Report the max number of bytes transferred for an ATA write command.
virtual IOReturn reportMaxWriteTransfer ( UInt64 blocksize,
UInt64 * max);
//-----------------------------------------------------------------------
// Returns the maximum addressable sector number.
virtual IOReturn reportMaxValidBlock ( UInt64 * maxBlock );
//-----------------------------------------------------------------------
// Report whether the media is currently present, and whether a media
// change has been registered since the last reporting.
virtual IOReturn reportMediaState ( bool * mediaPresent,
bool * changed );
//-----------------------------------------------------------------------
// Report whether the media is removable.
virtual IOReturn reportRemovability ( bool * isRemovable );
//-----------------------------------------------------------------------
// Report if the media is write-protected.
virtual IOReturn reportWriteProtection ( bool * isWriteProtected );
//-----------------------------------------------------------------------
// Gets the write cache state.
IOReturn getWriteCacheState ( bool * enabled );
//-----------------------------------------------------------------------
// Sets the write cache state.
IOReturn setWriteCacheState ( bool enabled );
//-----------------------------------------------------------------------
// Client calls this before making a request which could cause I/O to
// happen.
virtual void checkPowerState ( void );
//-----------------------------------------------------------------------
// Checks to see if we are in a good power state to fulfill the request
//
virtual void handleCheckPowerState ( void );
//-----------------------------------------------------------------------
// Handles power state changes
//
virtual void handlePowerChange ( void );
//-----------------------------------------------------------------------
// Handles messages (notifications) from our provider.
virtual IOReturn message ( UInt32 type,
IOService * provider,
void * argument ) APPLE_KEXT_OVERRIDE;
//-----------------------------------------------------------------------
// Returns the device type.
virtual const char * getDeviceTypeName ( void );
//-----------------------------------------------------------------------
// Sends an ATA SMART command to the device.
/* Added with 10.1.4 */
OSMetaClassDeclareReservedUsed ( IOATABlockStorageDriver_PD, 1 )
virtual IOReturn sendSMARTCommand ( IOATACommand * command );
// Binary Compatibility reserved method space
OSMetaClassDeclareReservedUnused ( IOATABlockStorageDriver_PD, 2 );
OSMetaClassDeclareReservedUnused ( IOATABlockStorageDriver_PD, 3 );
OSMetaClassDeclareReservedUnused ( IOATABlockStorageDriver_PD, 4 );
OSMetaClassDeclareReservedUnused ( IOATABlockStorageDriver_PD, 5 );
OSMetaClassDeclareReservedUnused ( IOATABlockStorageDriver_PD, 6 );
OSMetaClassDeclareReservedUnused ( IOATABlockStorageDriver_PD, 7 );
OSMetaClassDeclareReservedUnused ( IOATABlockStorageDriver_PD, 8 );
OSMetaClassDeclareReservedUnused ( IOATABlockStorageDriver_PD, 9 );
OSMetaClassDeclareReservedUnused ( IOATABlockStorageDriver_PD, 10 );
OSMetaClassDeclareReservedUnused ( IOATABlockStorageDriver_PD, 11 );
OSMetaClassDeclareReservedUnused ( IOATABlockStorageDriver_PD, 12 );
OSMetaClassDeclareReservedUnused ( IOATABlockStorageDriver_PD, 13 );
OSMetaClassDeclareReservedUnused ( IOATABlockStorageDriver_PD, 14 );
OSMetaClassDeclareReservedUnused ( IOATABlockStorageDriver_PD, 15 );
OSMetaClassDeclareReservedUnused ( IOATABlockStorageDriver_PD, 16 );
};
#endif /* _IO_ATA_BLOCKSTORAGE_DRIVER_PD_H_ */