1/*
2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25
26/*!
27  @header IOATAPIProtocolTransport
28  Contains the class definition for IOATAPIProtocolTransport.
29*/
30
31
32#ifndef _IOKIT_IO_ATAPI_PROTOCOL_TRANSPORT_H_
33#define _IOKIT_IO_ATAPI_PROTOCOL_TRANSPORT_H_
34
35#define kIOPropertyATAPIMassStorageCharacteristics 		"ATAPI Mass Storage Characteristics"
36
37#if defined(KERNEL) && defined(__cplusplus)
38
39/* General IOKit includes */
40#include <IOKit/IOLib.h>
41#include <IOKit/IOMessage.h>
42#include <IOKit/IOService.h>
43#include <IOKit/IOCommandPool.h>
44
45/* IOKit ATA Family includes */
46#include <IOKit/ata/IOATADevice.h>
47#include <IOKit/ata/IOATATypes.h>
48
49/* IOKit ATA Storage includes */
50#include <IOKit/storage/ata/IOATAStorageDefines.h>
51
52/* SCSI Architecture Model Family includes */
53#include <IOKit/scsi/IOSCSIProtocolServices.h>
54
55// Forward class declaration
56class IOATAPIProtocolTransport;
57
58/*!
59	@typedef ATAPIClientData
60	@param cmd IOATACommand for request.
61	@param self Pointer to the object.
62	@param scsiTask SCSITaskIdentifier of request.
63	@discussion This structure is stuffed into the refcon so we can associate which
64	IOATACommand and SCSITaskIdentifier is completing.
65*/
66
67struct ATAPIClientData
68{
69	IOATACommand *				cmd;
70	IOATAPIProtocolTransport *	self;
71	SCSITaskIdentifier			scsiTask;
72};
73typedef struct ATAPIClientData ATAPIClientData;
74
75
76/*!
77	@class IOATAPIProtocolTransport
78	@abstract SCSI Protocol Driver Family for ATAPI Devices.
79	@discussion IOATAPIProtocolTransport contains all the bus specific support for ATAPI compliant devices.
80	To add vendor specific features or workarounds you will sub-class the appropriate
81	methods of this family.
82*/
83
84class IOATAPIProtocolTransport : public IOSCSIProtocolServices
85{
86
87	OSDeclareDefaultStructors ( IOATAPIProtocolTransport )
88
89public:
90
91	// ---- IOService methods overridden ----
92
93	bool 			init 	( OSDictionary * propTable );
94
95	// The start method is called to start our services. If the device
96	// can be controlled by this object, then we return true, else we
97	// return false. start() is usually used to allocate resources once
98	// it is determined that the device can be controlled by this object.
99	virtual bool 	start 	( IOService * provider );
100
101	// The stop method is called to stop our services. It is primarily
102	// called for deallocation of resources.
103	virtual void 	stop 	( IOService *  provider );
104
105	// This method is our last chance to free all resources allocated.
106	virtual void	free	( void );
107
108
109protected:
110
111	// ---- member variables ----
112
113	IOATADevice *			fATADevice;
114	ataUnitID				fATAUnitID;
115	ataDeviceType			fATADeviceType;
116	ataSocketType			fATASocketType;
117	atapiConfig				fATAPIPacketConfig;
118	UInt8					fPIOMode;
119	UInt8					fDMAMode;
120	UInt8					fUltraDMAMode;
121	IOCommandGate *			fCommandGate;
122	IOCommandPool *			fCommandPool;
123	IOATACommand *			fResetCommand;
124	IOATACommand *			fConfigCommand;
125	IOATACommand *			fIdentifyCommand;
126	char					fRevision[kSizeOfATARevisionString + 1];
127	char					fModel[kSizeOfATAModelString + 1];
128	bool					fWakeUpResetOccurred;
129	bool					fPhysicallyConnected;
130
131	// Used for low-power polling support
132	thread_call_t			fPollingThread;
133
134	UInt16					fDeviceIdentifyData[256];
135	IOMemoryDescriptor *	fDeviceIdentifyBuffer;
136	bool					fResetInProgress;
137
138	// Binary Compatibility instance variable expansion
139	struct ExpansionData
140	{
141		UInt32		fSemaphore;
142		UInt32		fMediaNotifyValue;
143	};
144	ExpansionData * reserved;
145
146	// ---- IOService methods overridden ----
147
148	// The message method is used to listen to messages from our provider, the ATA controller.
149	// It sends messages for bus reset notifications and for device removal (such as MediaBay,
150	// PC card, etc.)
151	virtual IOReturn message ( UInt32 type, IOService * provider, void * argument = 0 );
152
153	// ---- Protocol transport methods overridden ----
154
155	// Send a SCSI Command to the device.  If the command was sent to the
156	// device and is pending completion, the subclass should return true and
157	// return back the kSCSIServiceResponse_Request_In_Process response.
158	// If the command completes immediately with an error, the subclass will
159	// return true and return back the appropriate status.
160	// if the subclass is currently processing all the commands it can, the
161	// subclass will return false and the command will be resent next time
162	// CommandCompleted is called.
163	virtual bool SendSCSICommand ( 	SCSITaskIdentifier 		request,
164									SCSIServiceResponse * 	serviceResponse,
165									SCSITaskStatus *		taskStatus );
166
167	// This is a stub - not implemented in upper layer yet. Eventually, there
168	// will be a way to abort a task or task set and this method will be called.
169	// It will abort any commands which have not been executed by the ATA controller
170	virtual SCSIServiceResponse AbortSCSICommand ( SCSITaskIdentifier request );
171
172	// The IsProtocolServiceSupported method will return true if the protocol
173	// layer supports the specified feature.
174	virtual bool IsProtocolServiceSupported ( SCSIProtocolFeature feature, void * serviceValue );
175
176	// The HandleProtocolServiceFeature method will return true if the protocol
177	// layer properly handled the specified feature.
178	virtual bool HandleProtocolServiceFeature ( SCSIProtocolFeature feature, void * serviceValue );
179
180	// ------ Power Management Support ------
181
182	// The HandlePowerOff method is called to do any bus specific activity
183	// necessary before shutting down and going to sleep.
184	virtual IOReturn 		HandlePowerOff 	( void );
185
186	// The HandlePowerOn method is called to do any bus specific activity
187	// necessary to recover from power-on/wake from sleep (e.g. device reset on ATAPI)
188	virtual IOReturn 		HandlePowerOn 	( void );
189
190
191	// ---- Methods defined by this class ----
192
193	// Static callback proc for all SCSITask objects, it calls through to
194	// SCSITaskCallbackFunction.
195	static void 			sSCSITaskCallbackProc ( IOATACommand * cmd );
196
197	// Callback proc for synchronous ATA only type commands.
198	static void 			sATACallbackSync ( IOATACommand * cmd );
199
200	// Callback proc for asynchronous ATAPI resets.
201	static void 			sATAPIResetCallback ( IOATACommand * cmd );
202
203	// Callback proc that does nothing.
204	static void 			sATAPIVoidCallback ( IOATACommand * cmd );
205
206	// State machine for device configuration.
207	static void				sATAPIConfigStateMachine ( IOATACommand * cmd );
208
209	// Used for low-power polling.
210	static void				sPollStatusRegister ( void * xptDriver, void * refCon );
211
212	// Static callback for low-power polling.
213	static void				sPollStatusRegisterCallback ( IOATACommand * cmd );
214
215	// This method is called by the SCSITaskCallbackFunction and it calls the
216	// inherited CommandCompleted message with the results of the task.
217	virtual void CompleteSCSITask ( SCSITaskIdentifier 	scsiTask,
218									SCSIServiceResponse serviceResponse,
219									SCSITaskStatus		taskStatus );
220
221	// The SCSITaskCallbackFunction method is called by the static callback procedure
222	// to complete SCSITask operations. This method may be subclassed if a device
223	// workaround is necessary.
224	virtual void SCSITaskCallbackFunction ( IOATACommand * 		cmd,
225											SCSITaskIdentifier 	scsiTask );
226
227	// The ReportATAPIDeviceType method returns the ataDeviceType for ATAPI
228	virtual ataDeviceType 	ReportATAPIDeviceType ( void ) const;
229
230	// The InspectDevice method is called to inspect the ATA device and verify
231	// that it is a device which can be controlled by this object
232	virtual bool			InspectDevice ( IOATADevice * ataDevice );
233
234	// The AllocateATACommandObjects method is called to allocate a pool of
235	// IOATACommands for general purpose I/O usage.
236	virtual void 			AllocateATACommandObjects ( void );
237
238	// The DeallocateATACommandObjects method is called to deallocate a pool of
239	// IOATACommands for general purpose I/O usage.
240	virtual void 			DeallocateATACommandObjects ( void );
241
242	// The GetATACommandObject method is called to retrieve a command from
243	// the pool. Pass true to allow the method to sleep waiting for a command,
244	// else pass false. If false is passed, there is NO guarantee that a valid
245	// command will be returned. If true is passed, it IS guaranteed that a
246	// valid command will be returned, but the thread may be slept waiting for
247	// those resources.
248	virtual IOATACommand *	GetATACommandObject	( bool okToSleep = true );
249
250	// The ReturnATACommandObject method is called to return a command to
251	// the pool.
252	virtual void			ReturnATACommandObject	( IOATACommand * cmd );
253
254	// The sSwapBytes16 method is used to word-swap the Device Identify data
255	// on big endian systems. Since all identify data is returned in little endian
256	// values, it must be word-swapped before inspected.
257	static void				sSwapBytes16 ( UInt8 * buffer, IOByteCount numBytesToSwap );
258
259	// The sConvertHighestBitToNumber method is used to find the highest bit in a
260	// word and return a numeric value.	This is used to find the highest possible
261	// values for PIO, DMA, and UltraDMA transfer modes.
262	static UInt8			sConvertHighestBitToNumber ( UInt16 bitField );
263
264	// The sSetWakeupResetOccurred method is used to safely set member variables
265	// behind the command gate.
266	static void				sSetWakeupResetOccurred ( IOATAPIProtocolTransport * driver,
267												   	  bool resetOccurred );
268
269	// The sCheckWakeupResetOccur method is used to safely check member variables
270	// behind the command gate.
271	static void				sCheckWakeupResetOccurred ( IOATAPIProtocolTransport * driver,
272														bool * resetOccurred );
273
274	// The DidWakeupResetOccur method is used to safely find out if a reset
275	// occurred while we were asleep.
276	virtual bool			CheckWakeupResetOccurred ( void );
277
278	// The WakeupResetOccurred method is used to safely set/clear the reset flag.
279	virtual void			SetWakeupResetOccurred ( bool resetOccurred );
280
281	// The SetPIOTransferMode method is used to set the programmed input-output (PIO)
282	// transfer mode. The highest value reported by the device is used.
283	virtual IOReturn		SetPIOTransferMode ( IOATACommand * cmd, bool forceSync );
284
285	// The SetDMATransferMode method is used to set the direct memory access (DMA)
286	// transfer mode. The highest value reported by the device is used.
287	virtual IOReturn		SetDMATransferMode ( IOATACommand * cmd, bool forceSync );
288
289	// The IdentifyAndConfigureATAPIDevice method is called to correctly identify
290	// and configure an ATAPI device.
291	virtual IOReturn 		IdentifyAndConfigureATAPIDevice ( void );
292
293	// The ConfigureATAPIDevice method is called to correctly configure the ATAPI
294	// device. It currently configures any PIO/DMA/UDMA transfer modes but may be
295	// expanded in the future.
296	virtual IOReturn 		ConfigureATAPIDevice ( void );
297
298	// The ReconfigureATAPIDevice method is called to correctly reconfigure the ATAPI
299	// device after a reset event has occurred (bus reset or device reset). It
300	// currently reconfigures any PIO/DMA/UDMA transfer modes but may be expanded in
301	// the future.
302	virtual IOReturn 		ReconfigureATAPIDevice ( void );
303
304	// The IdentifyATAPIDevice method is called to correctly identify the ATAPI
305	// device. It currently issues the Identify ATAPI Device packet command and
306	// uses the data to correctly configure the device.
307	virtual IOReturn 		IdentifyATAPIDevice ( void );
308
309	// The ResetATAPIDevice method is called to issue a Device Reset (also known
310	// as a SOFT RESET). This method will only reset the specified device on the
311	// bus.
312	virtual IOReturn 		ResetATAPIDevice ( void );
313
314	// The SendATASleepCommand method is called to put an ATAPI drive in sleep
315	// mode.
316	virtual IOReturn		SendATASleepCommand ( void );
317
318	// The EnablePollingOfStatusRegister method is called to set up a timer for
319	// the call to PollStatusRegister. It is called when the SCSI Application Layer
320	// driver wants to enable low-power polling and after a poll which does not
321	// see a change in the register status.
322	virtual void			EnablePollingOfStatusRegister ( void );
323
324	// The DisablePollingOfStatusRegister method is called to cancel any thread
325	// call which is doing a poll and drop the retain count on the object.
326	virtual void			DisablePollingOfStatusRegister ( void );
327
328	// The PollStatusRegister method is used to do low-power polling on drives which
329	// support it. This feature is enabled by the SCSI Application Layer driver.
330	virtual void			PollStatusRegister ( void * refCon );
331
332	// Callback method for the polling of the status register.
333	virtual void			PollStatusRegisterCallback ( IOATACommand * cmd );
334
335	// The TurnDrivePowerOff method is called to turn power to the drive OFF
336	IOReturn				TurnDrivePowerOff ( void );
337
338	IOReturn				SendCommand ( IOATACommand * cmd );
339	IOReturn				GatedWaitForRequest ( void * data );
340
341private:
342
343	// Binary Compatibility reserved method space
344	OSMetaClassDeclareReservedUnused ( IOATAPIProtocolTransport, 1 );
345	OSMetaClassDeclareReservedUnused ( IOATAPIProtocolTransport, 2 );
346	OSMetaClassDeclareReservedUnused ( IOATAPIProtocolTransport, 3 );
347	OSMetaClassDeclareReservedUnused ( IOATAPIProtocolTransport, 4 );
348	OSMetaClassDeclareReservedUnused ( IOATAPIProtocolTransport, 5 );
349	OSMetaClassDeclareReservedUnused ( IOATAPIProtocolTransport, 6 );
350	OSMetaClassDeclareReservedUnused ( IOATAPIProtocolTransport, 7 );
351	OSMetaClassDeclareReservedUnused ( IOATAPIProtocolTransport, 8 );
352	OSMetaClassDeclareReservedUnused ( IOATAPIProtocolTransport, 9 );
353	OSMetaClassDeclareReservedUnused ( IOATAPIProtocolTransport, 10 );
354	OSMetaClassDeclareReservedUnused ( IOATAPIProtocolTransport, 11 );
355	OSMetaClassDeclareReservedUnused ( IOATAPIProtocolTransport, 12 );
356	OSMetaClassDeclareReservedUnused ( IOATAPIProtocolTransport, 13 );
357	OSMetaClassDeclareReservedUnused ( IOATAPIProtocolTransport, 14 );
358	OSMetaClassDeclareReservedUnused ( IOATAPIProtocolTransport, 15 );
359	OSMetaClassDeclareReservedUnused ( IOATAPIProtocolTransport, 16 );
360
361};
362
363#endif /* defined(KERNEL) && defined(__cplusplus) */
364
365#endif	/* _IOKIT_IO_ATAPI_PROTOCOL_TRANSPORT_H_ */