1/*
2 * Copyright 2009, Michael Lotz, mmlr@mlotz.ch.
3 * Copyright 2008, Marcus Overhagen.
4 * Copyright 2004-2010, Axel D��rfler, axeld@pinc-software.de.
5 * Copyright 2002-2003, Thomas Kurschel.
6 *
7 * Distributed under the terms of the MIT License.
8 */
9#ifndef ATA_PRIVATE_H
10#define ATA_PRIVATE_H
11
12
13#include <ata_types.h>
14#include <bus/ATA.h>
15#include <bus/SCSI.h>
16#include <condition_variable.h>
17#include <device_manager.h>
18#include <lock.h>
19#include <new>
20#include <safemode.h>
21#include <scsi_cmds.h>
22#include <stdio.h>
23#include <string.h>
24#include <util/AutoLock.h>
25
26#include "ATACommands.h"
27#include "ATAInfoBlock.h"
28#include "ATATracing.h"
29
30
31#define ATA_MAX_DMA_FAILURES		3
32#define ATA_STANDARD_TIMEOUT		10 * 1000 * 1000
33#define ATA_RELEASE_TIMEOUT			10 * 1000 * 1000
34#define ATA_SIGNATURE_ATA			0x0000
35#define ATA_SIGNATURE_ATAPI			0xeb14
36#define ATA_SIGNATURE_SATA			0xc33c
37#define ATA_SIM_MODULE_NAME			"bus_managers/ata/sim/driver_v1"
38#define ATA_CHANNEL_ID_GENERATOR	"ide/channel_id"
39#define ATA_CHANNEL_ID_ITEM			"ide/channel_id"
40
41enum {
42	ATA_DEVICE_READY_REQUIRED	= 0x01,
43	ATA_IS_WRITE				= 0x02,
44	ATA_DMA_TRANSFER			= 0x04,
45	ATA_CHECK_ERROR_BIT			= 0x08,
46	ATA_WAIT_FINISH				= 0x10,
47	ATA_WAIT_ANY_BIT			= 0x20,
48	ATA_CHECK_DEVICE_FAULT		= 0x40
49};
50
51
52class ATADevice;
53class ATARequest;
54
55extern scsi_for_sim_interface *gSCSIModule;
56extern device_manager_info *gDeviceManager;
57
58bool copy_sg_data(scsi_ccb *ccb, uint offset, uint allocationLength,
59	void *buffer, int size, bool toBuffer);
60void swap_words(void *data, size_t size);
61
62
63class ATAChannel {
64public:
65								ATAChannel(device_node *node);
66								~ATAChannel();
67
68			status_t			InitCheck();
69			uint32				ChannelID() const { return fChannelID; }
70
71			// SCSI stuff
72			void				SetBus(scsi_bus bus);
73			scsi_bus			Bus() const { return fSCSIBus; }
74			status_t			ScanBus();
75
76			void				PathInquiry(scsi_path_inquiry *info);
77			void				GetRestrictions(uint8 targetID, bool *isATAPI,
78									bool *noAutoSense, uint32 *maxBlocks);
79			status_t			ExecuteIO(scsi_ccb *ccb);
80			status_t			Control(uint8 targetID, uint32 op, void *buffer,
81									size_t length);
82
83			// ATA stuff
84			status_t			SelectDevice(uint8 index);
85			uint8				SelectedDevice();
86
87			status_t			Reset();
88
89			bool				UseDMA() const { return fUseDMA; }
90
91			status_t			Wait(uint8 setBits, uint8 clearedBits,
92									uint32 flags, bigtime_t timeout);
93			status_t			WaitDataRequest(bool high);
94			status_t			WaitDeviceReady();
95			status_t			WaitForIdle();
96
97			void				PrepareWaitingForInterrupt();
98			status_t			WaitForInterrupt(bigtime_t timeout);
99			status_t			RecoverLostInterrupt();
100
101			// request handling
102			status_t			SendRequest(ATARequest *request, uint32 flags);
103			status_t			FinishRequest(ATARequest *request, uint32 flags,
104									uint8 errorMask);
105
106			// data transfers
107			status_t			PrepareDMA(ATARequest *request);
108			status_t			StartDMA();
109			status_t			FinishDMA();
110
111			status_t			ExecutePIOTransfer(ATARequest *request);
112
113			status_t			ReadRegs(ATADevice *device);
114			uint8				AltStatus();
115
116			status_t			ReadPIO(uint8 *buffer, size_t length);
117			status_t			WritePIO(uint8 *buffer, size_t length);
118
119			status_t			Interrupt(uint8 status);
120
121private:
122			status_t			_ReadRegs(ata_task_file *taskFile,
123									ata_reg_mask mask);
124			status_t			_WriteRegs(ata_task_file *taskFile,
125									ata_reg_mask mask);
126			status_t			_WriteControl(uint8 value);
127			uint8				_Status();
128
129			void				_FlushAndWait(bigtime_t waitTime);
130
131			bool				_DevicePresent(int device);
132
133			status_t			_ReadPIOBlock(ATARequest *request,
134									size_t length);
135			status_t			_WritePIOBlock(ATARequest *request,
136									size_t length);
137			status_t			_TransferPIOBlock(ATARequest *request,
138									size_t length, size_t *transferred);
139			status_t			_TransferPIOPhysical(ATARequest *request,
140									addr_t physicalAddress, size_t length,
141									size_t *transferred);
142			status_t			_TransferPIOVirtual(ATARequest *request,
143									uint8 *virtualAddress, size_t length,
144									size_t *transferred);
145
146			const char *		_DebugContext() { return fDebugContext; }
147
148private:
149			device_node *		fNode;
150			uint32				fChannelID;
151			ata_controller_interface *fController;
152			void *				fCookie;
153
154			spinlock			fInterruptLock;
155			ConditionVariable	fInterruptCondition;
156			ConditionVariableEntry fInterruptConditionEntry;
157			bool				fExpectsInterrupt;
158
159			status_t			fStatus;
160			scsi_bus			fSCSIBus;
161			uint8				fDeviceCount;
162			ATADevice **		fDevices;
163			bool				fUseDMA;
164			ATARequest *		fRequest;
165
166			char				fDebugContext[16];
167};
168
169
170class ATADevice {
171public:
172								ATADevice(ATAChannel *channel, uint8 index);
173	virtual						~ATADevice();
174
175	// SCSI stuff
176			status_t			ModeSense(ATARequest *request);
177			status_t			TestUnitReady(ATARequest *request);
178			status_t			SynchronizeCache(ATARequest *request);
179			status_t			Eject(ATARequest *request);
180			status_t			Inquiry(ATARequest *request);
181			status_t			ReadCapacity(ATARequest *request);
182			status_t			ReadCapacity16(ATARequest *request);
183	virtual	status_t			ExecuteIO(ATARequest *request);
184
185			void				GetRestrictions(bool *noAutoSense,
186									uint32 *maxBlocks);
187			status_t			Control(uint32 op, void *buffer, size_t length);
188
189	// ATA stuff
190	virtual	bool				IsATAPI() const { return false; }
191
192			bool				UseDMA() const { return fUseDMA; }
193			bool				Use48Bits() const { return fUse48Bits; }
194			size_t				BlockSize() const { return fBlockSize; }
195
196			status_t			Select();
197
198			ata_task_file *		TaskFile() { return &fTaskFile; }
199			ata_reg_mask		RegisterMask() const { return fRegisterMask; }
200
201			status_t			SetFeature(int feature);
202			status_t			DisableCommandQueueing();
203			status_t			ConfigureDMA();
204
205	virtual	status_t			Configure();
206			status_t			Identify();
207
208			status_t			ExecuteReadWrite(ATARequest *request,
209									uint64 address, uint32 sectorCount);
210
211	protected:
212			const char *		_DebugContext() { return fDebugContext; }
213
214			ATAChannel *		fChannel;
215			ata_device_infoblock fInfoBlock;
216			ata_task_file		fTaskFile;
217			ata_reg_mask		fRegisterMask;
218
219			bool				fUseDMA;
220			uint8				fDMAMode;
221			uint8				fDMAFailures;
222
223	private:
224			status_t			_FillTaskFile(ATARequest *request,
225									uint64 address);
226
227			uint64				fTotalSectors;
228			size_t				fBlockSize;
229			size_t				fPhysicalBlockSize;
230			size_t				fBlockOffset;
231			uint8				fIndex;
232			bool				fUse48Bits;
233
234			char				fDebugContext[16];
235};
236
237
238class ATAPIDevice : public ATADevice {
239public:
240								ATAPIDevice(ATAChannel *channel, uint8 index);
241	virtual						~ATAPIDevice();
242
243			status_t			SendPacket(ATARequest *request);
244	virtual	status_t			ExecuteIO(ATARequest *request);
245
246	virtual	bool				IsATAPI() const { return true; }
247
248	virtual	status_t			Configure();
249
250	private:
251			status_t			_FillTaskFilePacket(ATARequest *request);
252			status_t			_FinishRequest(ATARequest *request,
253									uint32 flags);
254
255private:
256			uint8				fPacket[12];
257};
258
259
260class ATARequest {
261public:
262								ATARequest(bool hasLock);
263								~ATARequest();
264
265			void				SetStatus(uint8 status);
266			uint8				Status() const { return fStatus; }
267
268			void				ClearSense();
269			void				SetSense(uint8 key, uint16 codeQualifier);
270			uint8				SenseKey() const { return fSenseKey; }
271			uint8				SenseCode() const { return fSenseCode; }
272			uint8				SenseQualifier() const
273									{ return fSenseQualifier; }
274
275			void				SetDevice(ATADevice *device);
276			ATADevice *			Device() const { return fDevice; }
277
278			void				SetTimeout(bigtime_t timeout);
279			bigtime_t			Timeout() const { return fTimeout; }
280
281			void				SetIsWrite(bool isWrite);
282			bool				IsWrite() const { return fIsWrite; }
283
284			void				SetUseDMA(bool useDMA);
285			bool				UseDMA() const { return fUseDMA; }
286
287			void				SetBytesLeft(uint32 bytesLeft);
288			size_t *			BytesLeft() { return &fBytesLeft; }
289
290			bool				HasData() const
291									{ return fCCB->data_length > 0; }
292			bool				HasSense() const { return fSenseKey != 0; }
293
294			status_t			Finish(bool resubmit);
295
296			// SCSI stuff
297			status_t			Start(scsi_ccb *ccb);
298			scsi_ccb *			CCB() { return fCCB; }
299
300			void				PrepareSGInfo();
301			void				AdvanceSG(uint32 bytes);
302
303			uint32				SGElementsLeft() const
304									{ return fSGElementsLeft; }
305			const physical_entry *CurrentSGElement() const
306									{ return fCurrentSGElement; }
307			uint32				CurrentSGOffset() const
308									{ return fCurrentSGOffset; }
309
310			void				SetOddByte(uint8 byte);
311			bool				GetOddByte(uint8 *byte);
312
313			void				RequestSense();
314
315private:
316			void				_FillSense(scsi_sense *sense);
317
318			const char *		_DebugContext() { return " request"; };
319
320			mutex				fLock;
321			bool				fHasLock;
322
323			uint8				fStatus;
324			uint8				fSenseKey;
325			uint8				fSenseCode;
326			uint8				fSenseQualifier;
327
328			ATADevice *			fDevice;
329			bigtime_t			fTimeout;
330			size_t				fBytesLeft;
331			bool				fIsWrite;
332			bool				fUseDMA;
333			scsi_ccb *			fCCB;
334
335			uint32				fSGElementsLeft;
336			const physical_entry *fCurrentSGElement;
337			uint32				fCurrentSGOffset;
338			bool				fHasOddByte;
339			uint8				fOddByte;
340};
341
342#endif // ATA_PRIVATE_H
343