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